gpt4 book ai didi

clojure - Clojure atom 中的长时间运行函数

转载 作者:行者123 更新时间:2023-12-01 08:55:39 25 4
gpt4 key购买 nike

我有一个函数可以加载大量用户(这需要一段时间)并将它们存储在一个原子中。我想知道将用户加载到 let 绑定(bind)然后重置原子或仅将它们加载到原子重置中是否有任何区别!功能?

(let [all-users (get-users)]
(reset! users all-users))

(reset! users (get-users))

最佳答案

它们是相同的,这就是为什么

由于 reset! 是一个函数,因此对 (reset!users (get-users)) 的调用将与 Clojure 中的任何其他函数调用一样:每个调用中的 S 表达式将被评估,然后作为参数传递给函数。这意味着(get-users) 的评估将首先发生,并将结果传递给reset!。因此,这将与 let 表单完全相同。

swap!

对比

这些问题在 swap! 中发挥作用。因为您发送 swap! 一个要在事务内部调用的函数,所以您可以更好地控制长时间运行的作业是在事务内部还是外部发生。例如,如果你有函数 poll-users-updatesupdate-users-from-poll,你可以设置对第一个函数的调用发生在内部或外部交易:

; outside the transaction
(swap! users update-users-from-poll (poll-users-updates))
; inside the transaction
(swap! users (fn [users] (update-users-from-poll users (poll-users-updates))))

这里的第二种形式更有可能必须重新启动,因为更新功能需要更长的时间才能运行,从而为其他对原子的写入留出更多时间来强制重新启动。

相比之下,第一种形式不太可能强制重试,因此通常是首选。另一方面,如果您的 poll-users-updates 函数还需要对 users 数据的当前状态进行操作(例如,找到最最近更新的用户,以便更有效地进行投票),那么第二种方法可能是首选,因为它可以确保您在进行投票时拥有 users 的最新值。

关于重试和副作用

这突出了关于 STM 的内容是您的更新函数可能会被多次调用。说副作用函数是“危险在原子内部”可能有点强。虽然它们可能很危险,但最好假设它们是危险的。即使它们不是(例如效果为 idempotent 时,这意味着您调用一次和多次调用相同的东西),最好不要让它们产生副作用。 Clojure 的 refs 和 atom 都是如此,它们会在发生冲突时重试。相反,代理没有重试语义,因此在发送给代理的函数中有副作用是可以的。由于代理将更新函数排队并按顺序运行,因此不会发生冲突,因此无需重试。

关于clojure - Clojure atom 中的长时间运行函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27838864/

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