2011-01-06 64 views
6

我剛剛瀏覽了關於Clojure併發性的各種文檔,並且在網站(http://clojure.org/concurrent_programming)上介紹了該示例。瞭解Clojure併發性示例

(import '(java.util.concurrent Executors)) 
(defn test-stm [nitems nthreads niters] 
(let [refs (map ref (replicate nitems 0)) 
     pool (Executors/newFixedThreadPool nthreads) 
     tasks (map (fn [t] 
        (fn [] 
        (dotimes [n niters] 
         (dosync 
         (doseq [r refs] 
          (alter r + 1 t)))))) 
       (range nthreads))] 
(doseq [future (.invokeAll pool tasks)] 
    (.get future)) 
(.shutdown pool) 
(map deref refs))) 

我理解它能做什麼以及它是如何工作的,但我不明白,爲什麼第二個匿名函數fn需要[]?

非常感謝,

杜沙。

P.S.沒有這第二個fn []我得到NullPointerException。

回答

5

下面是使用高階函數的一個典型的例子:

;; a function returns another function 
(defn make-multiplyer [times] 
    (fn [x] 
    (* x times))) 

;; now we bind returned function to a symbol to use it later 
(def multiply-by-two (make-multiplyer 2)) 

;; let's use it 
(multiply-by-two 100) ; => 200 

在內部FN FN該代碼示例的工作方式相同。當map調用(fn [t](fn [] ...))時,它會得到內部的fn。

(def list-of-funcs (map (fn [t] 
          (fn [] (* t 10))) ; main part 
         (range 5))) 
;; Nearly same as 
;; (def list-of-funcs (list (fn [] (* 0 10)) 
;;       (fn [] (* 1 10)) 
;;       ... 
;;       (fn [] (* 4 10)))) 


(for [i list-of-funcs] 
    (i)) 
; => (0 10 20 30 40) 

更新:正如亞歷克斯說的代碼示例中的任務必然要被傳遞然後.invokeAll可調用的列表()。

2

第一個fn是map用於創建fn的seq的地方 - 每個線程都有一個。這是因爲任務是一系列功能!該方法.invokeAll()從Clojure.org: Special Forms

FNS期待可調用的集合(Clojure的函數實現可調用接口)

實現Java可贖回,可運行和比較器的接口。