我只是阅读有关Clojure并发性的各种文档,并在网站(http://clojure.org/concurrent_programming)上提供了相关示例。
(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 []?
非常感谢,
dusha。
P.S。如果没有第二个fn [],我会得到NullPointerException。
答案 0 :(得分: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)
更新:正如Alex所说,代码示例中的任务绑定到可以传递给.invokeAll()的callables列表。
答案 1 :(得分:2)
第一个fn是map用来创建fn的seq - 每个线程一个。这是因为任务是一系列功能!方法.invokeAll()期待一个Callables集合(Clojure函数实现Callable接口)
fns实现Java Callable,Runnable和Comparator接口。