为什么代理人返回零而不是等待在clojure?

时间:2016-10-16 07:02:31

标签: concurrency clojure

(def file (agent nil))

(defn read-file []
    (if (= @file nil)
        (do
            (println "read-file")
            (send-off file #(slurp %2) (io/resource "file.txt")))
        nil)
    @file)

如果我第一次调用read-file,则返回nil。对于所有后续调用,它将返回文件内容。这是为什么?当我使用atom时,它可以正常工作。同样为什么#(slurp %2)需要第二个参数?当我只给%时它不起作用?我收到以下错误:

clojure.lang.ArityException: Wrong number of args (2) passed to: core/read-file/fn--3603

2 个答案:

答案 0 :(得分:2)

代理上的Deref提供当前状态的快照。代理程序使用nil进行初始化,因此在初始状态下取消引用它会返回nil

如果您想等到结果可用,您可以在代理上使用future或致电await。如果只有一个动作产生结果,future将是我的第一选择。在这个特定的例子中,我只是编写(slurp (io/resource "file.txt"))而没有任何并发​​构造。

答案 1 :(得分:2)

代理是错误的并发原语。它具有您不想要的所有特征,而且没有您想要的特性。相反,由于您要缓存的内容是一项昂贵的操作,请使用延迟:

(let [file (delay (slurp (io/resource "file.txt")))]
  (defn read-file []
    @file))