Ref,Var,Agent,Atom之间的Clojure差异,包括示例


110

我对Clojure还是很陌生,你们能给我解释一下真实的场景吗?我的意思是在哪里使用Ref,Var,Agent,Atom。我读过书,但仍然无法理解真实的例子。

Answers:


174

我强烈建议使用“ Clojure的喜悦”或“对Clojure进行编程”来真正回答该问题,我可以简要总结一下每种动机:

首先,请观看有关身份概念的视频和/或在此处学习

  • 引用用于“多个身份”的协调同步访问。
  • 原子用于对单个身份的不协调同步访问。
  • 代理用于对单个身份的非协调异步访问。
  • 变量用于具有共享默认值的线程本地隔离身份

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

当仅一个身份需要更新时,将使用非协调访问,这是一种非常常见的情况。

当预期呼叫要等到所有身份都解决之后再继续时,才使用同步访问。

异步访问是“生与死”,它使身份在自己的时间内达到其新状态。


在协同访问中,如果我只想更改state-a,而state-b这样做的话,我仍然需要ref正确吗?因此,它不是在更改多个事物,而是在更改任何事物时引用多个事物吗?
event_jr 2015年

2
是的,如果您希望状态a中的新值基于a和b中值的一致组合,您似乎正确地理解到状态a和状态b必须都必须是引用。您需要在状态a和状态b彼此一致的上下文中计算出新值。当它们都是引用时,如果b在中途更改,则事务将重新启动并使用a和b的新值。考虑使用以下ensure函数:clojure.github.io/clojure/clojure.core-api.html#clojure.core/…来使此操作显式且高效。
亚瑟·乌尔菲特

3
也许可以添加对具有共享默认值的“隔离”的解释以完成答案?
Didier A.

1
“需要一起更改两个身份时使用协调访问...”。应该“改变”吗?
Carcigenicate's

40

引用用于需要在线程之间同步的状态。如果您需要跟踪一堆不同的东西,并且有时需要执行一次写入多个东西的操作,请使用引用。每当您有多个不同的状态时,使用引用并不是一个坏主意。

原子用于独立状态,需要在线程之间进行同步。如果您永远不需要同时更改原子状态和其他任何状态,则使用at原子是安全的(特别是,如果整个程序中只有一个状态,则可以将其置于原子中) 。举一个不平凡的例子,如果您尝试缓存某个函数的返回值(即记住它),则使用原子可能是安全的-该状态​​对于函数外部的所有内容都是不可见的,因此您不必担心关于函数内部的状态变化使任何事情搞砸了。

代理的主要要点是它们在不同的线程中运行。您可以获取代理的值,并告诉其将功能应用于其值,但是您不知道该功能何时运行或该功能将应用于什么值。

Vars用于需要基于每个线程存储内容的情况。如果您有一个多线程程序,并且每个线程都需要其自己的私有状态,则将该状态放入var中。

就现实世界中的示例而言,如果您提供要尝试的示例,我们可以告诉您使用什么。


32

当我第一次阅读这些类型时,我还很难理解我可以或应该在哪里使用每种类型,因此这是我的简单英语回答:

当数据不变时,请使用var。每当您使用def或大多数以deflike 开头的功能时,都会发生这种情况defn

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

当您必须同时更改两个或多个事物时,请使用ref。如果您熟悉,请考虑“数据库事务”。一个典型的例子是将钱从一个帐户转移到另一个帐户。每个帐户都可以存储在引用中,以便可以进行更改以使其看起来是原子的。

当您想更改某些内容但不在乎时,请使用代理。这可能是很长的计算,也可能是向文件或套接字写入内容。请注意,对于后者,您应该使用send-off

注意:我很欣赏这些功能还有很多,但是希望这可以为您提供一个起点。


1
非常感谢您的明确答复:-)极大地帮助了像我这样的Clojure新手。
gosukiwi

27

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

共享状态-何时使用var,atoms,agent和refs?

我希望它能帮助人们寻找该主题的答案。

@tunaci建议后的一些捷径:

Vars

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

创建后请勿更改var。从技术上讲这是可能的,但是出于许多原因,这是个坏主意。

原子

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

不要使用非幂等函数和长时间执行的函数

代理商

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

参考

引用的工作方式类似于数据库事务。写入和读取在dosync中受到保护。您可以在交易中安全地操作许多裁判。

和流程图使用哪一个时: 流程图

请查看网站上的图片,因为始终可以进行一些更新。

要给出完整的答案而不需要复制和上一篇文章,这是一个复杂且漫长的话题,因此请原谅我将您重定向到网站:)


By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.