Clojure Ref、Var、Agent、Atom 之间的差异以及示例
我对 Clojure 很陌生,你们能给我解释一下现实世界的场景吗?我的意思是,在哪里使用 Ref、Var、Agent、Atom。我读过书,但是仍然无法理解现实世界的例子。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
我对 Clojure 很陌生,你们能给我解释一下现实世界的场景吗?我的意思是,在哪里使用 Ref、Var、Agent、Atom。我读过书,但是仍然无法理解现实世界的例子。
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
接受
或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
发布评论
评论(5)
我强烈推荐“Clojure 的乐趣”或“Clojure 编程”,以获得这个问题的真正答案,我可以重现每个动机的简短片段:
首先观看 此视频介绍身份概念 和/或 在这里学习。
当两个身份需要一起更改时,使用协调访问,典型的例子是将资金从一个银行帐户转移到另一个银行帐户,它需要完全转移或根本不转移。
当只有一个身份需要更新时,使用不协调访问,这是一种非常常见的情况。
同步 访问用于当呼叫预计要等到所有身份都已确定后再继续时。
异步访问是“即发即忘”,让身份在自己的时间内达到新状态。
I highly recommend "The Joy of Clojure" or "programming Clojure" for a real answer to this question, I can reproduce a short snip-it of the motivations for each:
start by watching this video on the notion of Identity and/or studying here.
Coordinated access is used when two Identities needs to change together, the classic example is moving money from one bank account to another, it needs to either move completely or not at all.
Uncoordinated access is used when only one Identity needs to update, this is a very common case.
Synchronous access is used when the call is expected to wait until all Identities have settled before continuing.
Asynchronous access is "fire and forget" and let the Identity reach its new state in its own time.
Refs 用于需要在线程之间同步的状态。如果您需要跟踪一堆不同的事物,并且有时需要执行一次写入多个事物的操作,请使用 refs。任何时候你有多个不同的状态,使用 refs 并不是一个坏主意。
原子用于需要在线程之间同步的独立状态。如果你永远不需要同时改变原子的状态和其他任何东西,那么使用 atatom 是安全的(特别是,如果整个程序中只有一个状态,你可以把它放在一个原子中) 。作为一个重要的例子,如果您尝试缓存函数的返回值(即记忆它),使用原子可能是安全的 - 状态对于函数外部的所有内容都是不可见的,因此您无需担心关于函数内部的状态变化搞乱了一切。
代理的主要观点是它们在不同的线程中运行。您可以获取代理的值并告诉它对其值应用一个函数,但您不知道该函数何时运行或该函数将应用到什么值。
变量适用于需要在每个线程的基础上存储某些内容的情况。如果您有一个多线程程序,并且每个线程都需要自己的私有状态,则将该状态放入 var 中。
就现实世界的示例而言,如果您提供一个您想要做什么的示例,我们可以告诉您要使用什么。
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.
Atoms are for independent state that needs to be synchronized between threads. If you will never need to change the state of the atom and anything else at the same time, using at atom is safe (in particular, if there is only one piece of state in the entire program, you can put it in an atom). As a non-trivial example, if you are trying to cache the return values of a function (ie memoize it), using an atom is probably safe - the state is invisible to everything outside the function, so you don't need to worry about a state change inside the function messing anything up.
Agents primary point is that they run in a different thread. You can get the value of the agent and tell it to apply a function to its value, but you don't know when the function will run or what value the function will be applied to.
Vars are for when you need to store something on a per-thread basis. If you have a multi-threaded program and each thread needs its own private state, put that state in a var.
As far as real-world examples go, if you provide an example of what you are trying to do, we can tell you what to use.
当我第一次阅读这些类型时,我也很难理解我可以或应该在哪里使用每种类型,所以这是我的简单英语答案:
当数据不会改变时使用 var。每当您使用
def
或大多数以def
开头的函数(如defn
)时,就会发生这种情况。当您有单个项目发生变化时,请使用原子。例如,您想要向其添加项目的计数器或向量。
当您有两个或多个必须同时更改的内容时,请使用 ref。如果您熟悉的话,请考虑“数据库事务”。典型的例子是将资金从一个帐户转移到另一个帐户。每个帐户都可以存储在引用中,以便可以进行原子更改。
当您想要更改某些内容但不关心何时更改时,请使用代理。这可能是一个很长的计算或向文件或套接字写入一些内容。请注意,对于后者,您应该使用
send-off
。注意:我知道每个内容都有很多内容,但希望这能为您提供一个起点。
When I first read about these types, I also struggled to understand where I could or should use each one so here's my plain English answer:
Use a var when the data won't change. This happens whenever you use
def
or most functions that start withdef
likedefn
.Use an atom when you have a single item that changes. An example might be a counter or a vector that you want to add items to.
Use a ref when you have two or more things that must change at the same time. Think "database transactions" if you are familiar. The canonical example of this is transferring money from one account to another. Each account could be stored in a ref so that changes can be made to appear atomic.
Use an agent when you want something to change but you don't care when. This might be a long computation or writing something to a file or socket. Note that with the latter you should use
send-off
.Note: I appreciate that there is quite a lot more to each of these but hopefully this should give you a starting point.
我写了一篇文章,总结了它们之间的区别,并帮助选择何时使用哪一个。
共享状态 - 何时使用变量、原子、代理和引用?
我希望它能帮助人们寻找该主题的答案。
@tunaci 建议后文章中的一些快捷方式:
Vars
原子
代理
参考文献
以及使用哪一种时的流程图:
请查看网站上的图片,因为总是有可能进行一些更新。
这是一个复杂而漫长的话题,无法在没有复制和重复的情况下给出完整的答案。过去的文章,所以请原谅我将您重定向到网站:)
I wrote article with summary up the difference between them and help choose when use which one.
Share state - when use vars, atoms, agents and refs?
I hope it will help people looking answers in that topic.
Some shortcut from the article after @tunaci suggestion:
Vars
Atoms
Agents
Refs
And flowchart when use which one:
Please look at the image on website, because some updates are always possible.
It is complex and a long topic to give full answer without copy & past article, so please forgive me i redirect you to website :)
原子、参考文献和代理 - 这里有一些说明
http://blog.jayfields.com/2011/04/clojure-state -management.html
atoms, refs and agents - some illumination here
http://blog.jayfields.com/2011/04/clojure-state-management.html