2011-01-06 65 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可赎回,可运行和比较器的接口。