gpt4 book ai didi

Clojure 混淆 - 多进程环境中 map、doseq 的行为

转载 作者:行者123 更新时间:2023-12-01 08:59:18 26 4
gpt4 key购买 nike

在尝试复制一些 websockets 示例时,我遇到了一些我不理解且似乎无法找到文档的行为。简单来说,这是我在 lein 中运行的一个示例,它应该每秒为共享 map 中的每个元素运行一次函数:

(def clients (atom {"a" "b" "c" "d" }))

(def ticker-agent (agent nil))

(defn execute [a]
(println "execute")
(let [ keys (keys @clients) ]
(println "keys= " keys )
(doseq [ x keys ] (println x)))
;(map (fn [k] (println k)) keys)) ;; replace doseq with this?

(Thread/sleep 1000)
(send *agent* execute))


(defn -main [& args]
(send ticker-agent execute)
)

如果我用 map 运行它,我会得到

execute
keys= (a c)
execute
keys= (a c)
...

第一个令人困惑的问题:我知道我可能会错误地使用 map 因为没有返回值,但这是否意味着内部 println 被优化掉了?特别是考虑到如果我在 repl 中运行它:

(map #(println %) '(1 2 3))

工作正常吗?

第二个问题 - 如果我使用 doseq 而不是 ma​​p 运行它,我可能会遇到执行代理停止的情况(我会在此处附加,但我有难以隔离/重建)。很明显,我遗漏了一些可能与锁定映射键集有关的东西?我什至能够将共享映射从原子中移出。clojure 映射上是否有默认同步?

最佳答案

map 是懒惰的。这意味着在从它重新运行的数据结构中访问结果之前,它不会计算任何结果。这意味着如果不使用它的结果,它将不会运行任何东西。

当您使用 repl 中的 map 时,repl 的打印阶段会访问数据,这会导致调用映射函数中的任何副作用。在函数内部,如果不研究返回值,映射函数不会产生任何副作用。

您可以使用 doall 强制对惰性序列进行全面评估。如果您不需要结果值但希望确保调用所有副作用,则可以使用 dorun。您还可以使用非惰性的 mapv(因为向量从不惰性),并为您提供通常有用的关联数据结构(更好的随机访问性能,针对追加而不是预先进行优化)。

编辑:关于您问题的第二部分(从评论中移到此处)。

不,没有任何关于 doseq 会挂起你的执行,尝试检查 agent-error你的代理的状态,看看是否有一些异常,因为如果代理遇到错误条件,默认情况下会停止执行并停止接受新任务。您也可以使用set-error-modelset-error-handler!自定义代理的错误处理行为。

关于Clojure 混淆 - 多进程环境中 map、doseq 的行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21288825/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com