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

发布于 2025-01-02 01:10:12 字数 92 浏览 1 评论 0 原文

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

I'm very new to Clojure, Can you guys give me explanation with real world scenarios. I mean, where to use Ref, Var, Agent, Atom. I read book, but, still couldn't understand the real world examples.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

习惯那些不曾习惯的习惯 2025-01-09 01:10:12

我强烈推荐“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.

  • Refs are for Coordinated Synchronous access to "Many Identities".
  • Atoms are for Uncoordinated synchronous access to a single Identity.
  • Agents are for Uncoordinated asynchronous access to a single Identity.
  • Vars are for thread local isolated identities with a shared default value.

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.

浊酒尽余欢 2025-01-09 01:10:12

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.

吃→可爱长大的 2025-01-09 01:10:12

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

当数据不会改变时使用 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 with def like defn.

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.

淡淡的优雅 2025-01-09 01:10:12

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

共享状态 - 何时使用变量、原子、代理和引用?

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

@tunaci 建议后文章中的一些快捷方式:

Vars

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

创建后不要更改变量。技术上是可行的,但是
出于多种原因,这是个坏主意。

原子

每个线程共享对可变状态的访问。改变发生
同步地。当其他线程在运行过程中改变状态时重试。

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

代理

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

参考文献

Refs 的工作方式与数据库事务类似。写入和读取是
在 dosync 中进行保护。您可以在交易中安全地操作许多引用。

以及使用哪一种时的流程图:
流程图

请查看网站上的图片,因为总是有可能进行一些更新。

这是一个复杂而漫长的话题,无法在没有复制和重复的情况下给出完整的答案。过去的文章,所以请原谅我将您重定向到网站:)

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

Vars are global for every threads.

Do not change vars after create. It is technically possible, but it is
bad idea for many reasons.

Atoms

Share access to mutable state for every threads. Change occurs
synchronously. Retry when other thread change the state during run.

Do not use not idempotent functions and functions with long time
execution

Agents

Share access to mutable state for every threads. Change occurs
asynchronously.

Refs

Refs works similar to database transactions. Write and read are
protect in dosync. You can operate on many refs safe in transaction.

And flowchart when use which one:
flowchart

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 :)

执妄 2025-01-09 01:10:12

原子、参考文献和代理 - 这里有一些说明
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

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文