我是Clojure的新手,你能不能给我解释现实场景。我的意思是,在哪里使用Ref,Var,Agent,Atom。我读过书,但是,仍然无法理解现实世界的例子。
答案 0 :(得分:157)
我强烈推荐“Clojure的喜悦”或“编程Clojure”来回答这个问题的真实答案,我可以重现一下每个动机的简短内容:
首先观看this video on the notion of Identity和/或studying here。
协调访问权限,典型的例子是将资金从一个银行帐户转移到另一个银行帐户,它需要完全移动或根本不移动。
当只有一个Identity需要更新时,使用不协调访问,这是一种非常常见的情况。
同步访问是在预期呼叫等到所有身份都已确定之后才使用的。
异步访问是“一劳永逸”,让身份在其自己的时间内达到新的状态。
答案 1 :(得分:38)
Refs用于需要在线程之间同步的状态。如果你需要跟踪一堆不同的东西,你有时需要做一些写入多个事情的操作,使用refs。每当你有多个不同的状态时,使用refs并不是一个坏主意。
Atoms用于需要在线程之间同步的独立状态。如果你永远不需要同时改变原子和其他任何东西的状态,那么使用at atom是安全的(特别是,如果整个程序中只有一个状态,你可以把它放在一个原子中) 。作为一个非常重要的例子,如果你试图缓存一个函数的返回值(即memoize它),使用一个原子可能是安全的 - 状态对函数外的所有东西都是不可见的,所以你不必担心关于功能内部的状态变化搞乱任何事情。
代理主要的一点是它们在不同的线程中运行。您可以获取代理的值并告诉它将函数应用于其值,但您不知道该函数何时运行或该函数将应用于什么值。
Vars适用于需要在每个线程上存储内容的情况。如果您有一个多线程程序并且每个线程都需要自己的私有状态,请将该状态放在var。
中就真实世界的例子而言,如果你提供一个你想要做的事情的例子,我们可以告诉你要使用什么。
答案 2 :(得分:29)
当我第一次阅读这些类型时,我也很难理解我能够或应该使用每一种类型,所以这里是我的简单英语答案:
当数据不会改变时使用var。只要您使用def
或大多数以def
开头的函数(例如defn
),就会发生这种情况。
当您有一个更改的项目时使用原子。一个示例可能是您要添加项目的计数器或矢量。
如果您有两件或多件必须同时更改的东西,请使用参考号。如果您熟悉,请考虑“数据库事务”。这种规范的例子是将钱从一个账户转移到另一个账户。每个帐户都可以存储在ref中,以便可以使更改显示为原子。
当您想要更改某些内容时使用代理但您何时不关心。这可能是一个很长的计算或写入文件或套接字。请注意,对于后者,您应该使用send-off
。
注意:我很欣赏其中每一项都有很多,但希望这会给你一个起点。
答案 3 :(得分:21)
我写了文章,总结了它们之间的区别,并帮助选择何时使用哪一个。
Share state - when use vars, atoms, agents and refs?
我希望它能帮助人们在该主题中寻找答案。
@tunaci建议后文章的一些捷径:
<强>瓦尔强>
每个线程的Vars都是全局的。
创建后不要更改变量。这在技术上是可行的,但确实如此 坏主意有很多原因。
<强>原子强>
为每个线程共享对可变状态的访问权限。发生变化 同步。其他线程在运行期间更改状态时重试。
长时间不要使用非幂等函数和函数 执行
<强>剂强>
为每个线程共享对可变状态的访问权限。发生变化 异步。
<强>参考文献强>
Refs与数据库事务类似。写和读 在dosync中保护。您可以在交易中操作许多安全的参考。
请查看网站上的图片,因为总有一些更新。
在没有副本的情况下提供完整答案是一个复杂而漫长的话题。过去的文章,请原谅我,我将你重定向到网站:)
答案 4 :(得分:4)
原子,refs和agent - 这里有一些照明 http://blog.jayfields.com/2011/04/clojure-state-management.html