Clojure-如何自动初始化一次

Clojure-如何自动初始化一次,clojure,Clojure,我正在使用一个代理,它引用一个集合来跟踪我需要通知事件的用户。我希望它在第一次被调用时自动初始化,所以到目前为止我已经这样做了: (声明通知用户!) (需要通知的def用户) (未来 (def_utn(agent{})) (添加监视\u utn:utn通知用户!) _(utn) (defn更新用户[用户id] (发送@users通知conj用户id)) (defn通知用户![密钥引用旧状态新状态] (println旧状态“->”新状态) 这似乎有效,但我想知道这种方法是否存在我不知道的任何问题

我正在使用一个代理,它引用一个集合来跟踪我需要通知事件的用户。我希望它在第一次被调用时自动初始化,所以到目前为止我已经这样做了:

(声明通知用户!)
(需要通知的def用户)
(未来
(def_utn(agent{}))
(添加监视\u utn:utn通知用户!)
_(utn)
(defn更新用户[用户id]
(发送@users通知conj用户id))
(defn通知用户![密钥引用旧状态新状态]
(println旧状态“->”新状态)

这似乎有效,但我想知道这种方法是否存在我不知道的任何问题。

我自己仍然是一名学习者,但我想我可以帮助您以更惯用的方式表达您所写的内容

首先,在开始使用帮助器函数之前先定义它们,除非有特定的原因需要首先声明它们。我以这种方式测试了代码多次,效果很好

(defn notify-users [key reference old-state new-state]
  (println old-state " -> " new-state))

(defonce users-to-notify
  (future
    (let [utn (agent #{})]
    (add-watch utn :utn notify-users)
    utn)))

(defn update-user! [user-id]
  (send-off @users-to-notify conj user-id))
另外,这可能是风格的问题,但我通常只在顶层使用def,以避免下一个程序员在阅读我的代码时混淆范围<在这种情况下,code>let更好,如果您测试它,您将看到代理在用户中持续存在以通知变量。感叹号用于指示变异函数,而不是副作用函数,通常,下划线用于指示作为参数传递到函数中的值,该参数不会在生成的代码中使用。使用需要绑定的
dotimes
函数可以找到一个常见示例:

(dotimes [_ 10] (println "I'm a cheeky monkey!"))

我还将def更改为defonce,但您应该注意,defonce不是线程安全的,这意味着expr可能会得到多次评估

重要的是在它被调用之前不被初始化吗;我宁愿不担心它。使用未来的全部意义在于只创建一次初始状态,即第一次调用它。我在运行代码时没有遇到任何错误。你能答应我吗
(def notify users!(promise))
然后是以后的
(future(交付notify users!(fn[键引用旧状态新状态](println旧状态“->“新状态”))
我已经编辑了我的答案,请检查它是否有用。还有,我对德里夫的批评不好。我不知道你在送别的时候用它来让特工离开未来。当我第一次运行它时,它在我的机器上抛出了一个错误,但是当我重新加载我的repl时,它就像你说的那样工作正常。