Ref、 Var、 Agent、 Atom 之间的 Clojure 差异及示例

我对 Clojure 很陌生,你们能给我解释一下现实世界的情景吗。我的意思是,在哪里使用裁判,瓦尔,代理人,原子。我读了书,但是,还是不能理解现实世界的例子。

23900 次浏览

Refs are for state that needs to be synchronized between threads. If you need to keep track of a bunch of different things and you will sometimes need to do operations that write to several of the things at once, use refs. Any time you have multiple different pieces of state, using refs isn't a bad idea.

原子用于需要在线程之间同步的独立状态。如果您永远不需要同时更改 atom 的状态和其他任何内容,那么使用 at atom 是安全的(特别是,如果整个程序中只有一个状态,那么您可以将其放入一个 atom 中)。作为一个重要的例子,如果你试图缓存一个函数的返回值(即制表它) ,使用一个原子可能是安全的——这个状态对于函数之外的所有东西都是不可见的,所以你不需要担心函数内部的状态改变会把任何东西搞乱。

代理的主要特点是它们在不同的线程中运行。您可以获取代理的值,并告诉它将一个函数应用于它的值,但是您不知道该函数将何时运行,或者该函数将应用于哪个值。

Vars 用于在每个线程基础上存储某些内容。如果您有一个多线程程序,并且每个线程都需要自己的私有状态,那么将该状态放在 var 中。

至于现实世界的例子,如果您提供了一个示例,说明您正在尝试做什么,我们可以告诉您使用什么。

我强烈推荐“ Clojure 的乐趣”或者“编程 Clojure”作为这个问题的真正答案,我可以复制一个简短的片段——每个片段的动机:

start by watching 这个关于身份概念的视频 and/or studying here.

  • Refs are for Coordinated Synchronous access to "Many Identities".
  • 原子用于 不协调同步访问单个身份。
  • 代理用于 Uncoordinated asynchronous访问单个标识。
  • Vars 用于具有共享默认值的线程本地 孤立的身份

当两个身份需要一起更改时,使用协调 访问,经典的例子是将钱从一个银行账户转移到另一个账户,它需要完全转移或根本不转移。

当只有一个 Identity 需要更新时,使用不协调的 访问,这是一种非常常见的情况。

当调用需要等到所有标识都解决之后才能继续时,使用同步 访问。

异步访问是“激活并忘记”,让 Identity 在自己的时间内达到新的状态。

原子,参考文献和代理人-一些照明在这里 Http://blog.jayfields.com/2011/04/clojure-state-management.html

当我第一次读到这些类型的文章时,我也很难理解在哪些地方我可以或者应该使用它们,所以这里是我的简单英语答案:

当数据不会更改时,使用 var。只要使用 def或大多数以 def开头的函数(如 defn) ,就会发生这种情况。

当单个项目发生更改时,请使用原子。示例可能是要向其中添加项的计数器或向量。

当您有两个或多个必须同时更改的事项时,请使用 ref。如果您熟悉的话,可以考虑“数据库事务”。典型的例子是将钱从一个账户转移到另一个账户。每个帐户都可以存储在一个 ref 中,这样就可以将更改显示为原子的。

当你想要改变某些事情但是你不在乎什么时候改变的时候,你可以使用一个代理。这可能是一个很长的计算过程,或者将某些内容写入文件或套接字。请注意,对于后者,您应该使用 send-off

注意: 我很欣赏这里有很多更多的这些,但希望这应该给你一个起点。

我写了一篇文章,总结了它们之间的区别,并帮助选择何时使用哪一个。

Share state - when use vars, atoms, agents and refs?

我希望它能帮助人们找到这个话题的答案。

在@tunaci 的建议之后,这篇文章给出了一些捷径:

瓦尔斯

对于每个线程,Vars 都是全局的。

Do not change vars after create. It is technically possible, but it is 出于很多原因,这是个坏主意。

原子

共享对每个线程可变状态的访问 当其他线程在运行期间更改状态时重试。

Do not use not idempotent functions and functions with long time 处决

探员们

共享对每个线程可变状态的访问 异步的。

裁判

引用的工作原理类似于数据库事务 您可以在事务中安全地操作多个参考文献。

以及使用哪一个的流程图: flowchart

Please look at the image on website, because some updates are always possible.

这是一个复杂和漫长的话题给予完整的答案,没有复制和过去的文章,所以请原谅我重新定向您的网站:)