Clojure参考项目是最新的?

时间:2012-09-03 13:22:37

标签: clojure lisp

从Clojure开始,我发现了Rich Hickey的演讲,他在基础Ant-Simulator上展示了Clojure的一些优势。

此代码是否仍被视为Clojure的良好参考?特别是当他递归地向代理发送函数以模拟游戏循环时的部分。 例如:

(defn animation [x]
  (when b/running
    (send-off *agent* #'animation))
    (. panel (repaint))
  (. Thread (sleep defs/animation-sleep-ms))
  nil)

修改

我对#'读者宏并不感兴趣,但更多的是它是惯用的/好的Clojure 递归地调用代理上的函数。

1 个答案:

答案 0 :(得分:3)

此片段在Clojure 1.4中是最新的。将函数提交回调用它的代理程序的函数是否惯用?是。

以下是使用类似方法递归计算阶乘的示例:

(defn fac [n limit total]
  (if (< n limit)
    (let [next-n (inc n)]
       (send-off *agent* fac limit (* total next-n)) 
       next-n)
     total))

 (def a (agent 1))

 (await (send-off a fac 5 1))
 ; => nil
 @a
 ;=> 120

<强>更新

上面是一个人为的例子,实际上并不是一个很好的例子,因为各种递归send-off调用和后面的await之间存在竞争条件。可能还有一些send-off调用要添加到代理的任务队列中。

我重写了以上内容:

(defn factorial-using-agent-recursive [x]
  (let [a (agent 1)]
    (letfn [(calc  [n limit total]
               (if (< n limit)
                 (let [next-n (inc n)]
                   (send-off *agent* calc limit (* total next-n))
                   next-n)
                 total))]
      (await (send-off a calc x 1)))
    @a))

并观察到以下行为:

user=> (for [x (range 10)] (factorial-using-agent-recursive 5))
(2 4 3 120 2 120 120 120 120 2)
user=> (for [x (range 10)] (factorial-using-agent-recursive 5))
(2 2 2 3 2 2 3 2 120 2)
user=> (for [x (range 10)] (factorial-using-agent-recursive 5))
(120 120 120 120 120 120 120 120 120 120)

故事的道德是:不要使用代理进行同步计算。将它们用于异步独立任务 - 例如更新显示给用户的动画:)