使用重置有什么区别!以及一个新的DEF,以更改与原子相关的变量的值?

发布于 2025-02-11 05:30:24 字数 1113 浏览 2 评论 0原文

根据Clojure的文档,reset!可以用作:

将原子的值设置为newval,而无需考虑当前值。 返回newval。

因此,我可以做:

user> (def my-test (atom 666))
#'user/my-test
user> my-test
#<Atom@66d7a880: 666>
user> @my-test
666
user> (reset! my-test 77)
77
user> my-test
#<Atom@66d7a880: 77>
user> @my-test
77

但是,使用另一个 def而不是reset!之间是否存在任何区别?

user> (def my-test (atom 666))
#'user/my-test
user> my-test
#<Atom@66d7a880: 666>
user> @my-test
666
user> (reset! my-test 77)
77
user> my-test
#<Atom@66d7a880: 77>
user> @my-test
77

;;;; converting it back to the original value via def

user> (def my-test (atom 666))
#'user/my-test
user> @my-test
666
user> my-test
#<Atom@7ce4f432: 666>
user> 

仅通过阅读Repl I 上的实验无法确定任何差异。但是我是Clojure的新手,所以我可能在这里很天真。

如果有任何区别,为什么我要使用重置!而不是 new def

According to Clojure's documentation, reset! can be used as:

Sets the value of atom to newval without regard for the current value.
Returns newval.

Thus, I can do:

user> (def my-test (atom 666))
#'user/my-test
user> my-test
#<Atom@66d7a880: 666>
user> @my-test
666
user> (reset! my-test 77)
77
user> my-test
#<Atom@66d7a880: 77>
user> @my-test
77

But, is there any difference between using another def instead of reset!?

user> (def my-test (atom 666))
#'user/my-test
user> my-test
#<Atom@66d7a880: 666>
user> @my-test
666
user> (reset! my-test 77)
77
user> my-test
#<Atom@66d7a880: 77>
user> @my-test
77

;;;; converting it back to the original value via def

user> (def my-test (atom 666))
#'user/my-test
user> @my-test
666
user> my-test
#<Atom@7ce4f432: 666>
user> 

Just by reading the experiments on the REPL I cannot identify any difference. But I am new to Clojure, so I am probably naive here.

If there is any difference, why should I use reset! instead of a new def?

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

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

发布评论

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

评论(4

千寻… 2025-02-18 05:30:24

您可以在问题中的depl输出中看到答案。当您编写(重置!A 1)时,您为现有原子提供了新的值。当您编写(DEF A(ATOM 1))时,您会得到一个全新的原子。为什么这很重要?因为某人可能对旧原子有另一个提及:在前一种情况下,他们看到了新价值,在后一种情况下,他们没有。例如:

(def a (atom 0))
(defn counter [c] (fn [] (swap! c inc)))
(def count-up (counter a))

(count-up) ; 1
(count-up) ; 2
(reset! a 0)
(count-up) ; 1 again

(def a (atom 0))
(defn counter [c] (fn [] (swap! c inc)))
(def count-up (counter a))

(count-up) ; 1
(count-up) ; 2
(def a (atom 0))
(count-up) ; 3, because the old atom still holds 2

You can see the answer in the REPL output in your question. When you write (reset! a 1), you give a new value to the existing atom. When you write (def a (atom 1)), you get a brand new atom. Why does this matter? Because someone may have another reference to the old atom: in the former case they see the new value, and in the latter case they don't. Compare, for example:

(def a (atom 0))
(defn counter [c] (fn [] (swap! c inc)))
(def count-up (counter a))

(count-up) ; 1
(count-up) ; 2
(reset! a 0)
(count-up) ; 1 again

with

(def a (atom 0))
(defn counter [c] (fn [] (swap! c inc)))
(def count-up (counter a))

(count-up) ; 1
(count-up) ; 2
(def a (atom 0))
(count-up) ; 3, because the old atom still holds 2
や三分注定 2025-02-18 05:30:24

更改为 Atoms 始终没有种族条件。新的效果不是。

Changes to atoms are always free of race conditions. New-def-ing is not.

伴我老 2025-02-18 05:30:24

clojure var是一个全局值,总的来说,它永远不会改变(与往常一样,每个规则都有例外)。例如,函数声明通常存储在var中。

clojure atom旨在指出一个可以更改的值。可以在全局var或局部变量绑定中保存原子(例如,(let ...)表单)。原子是螺纹安全的(这是其主要目的之一)。

如果您只是只使用一个线程来玩实验代码,那么您可以做很多马虎或危险的事情,没有问题。但是,您应该学习如何将每个工具用于其预期目的。


更详细的讨论:

A Clojure Var is meant to be a global value that, in general, never changes (as always, there are exceptions to every rule). As an example, function declarations are normally stored in a Var.

A Clojure Atom is meant to point to a value that can change. An atom may be held in a global Var or a local variable binding (e.g. in a (let ...) form). Atoms are thread-safe (this is one of their primary purposes).

If you are just playing around with experimental code with only one thread, you can do a lot of sloppy or dangerous stuff and there is no problem. However, you should learn how to use each tool for its intended purpose.


More detailed discussion:

作死小能手 2025-02-18 05:30:24

def创建一个新的原子(表示为原子分配新的存储空间 - 设置它 - 设置指针),而reset!仅重置现有原子(只是更改值在单元格中,指针指向)。
因此,reset!必须比def您可以通过以下方式测试:

(def n 10000000)

(time (dotimes [_ n] (def a (atom 1))))
## "Elapsed time: 2294.676443 msecs"


(def b (atom 1))
(time (dotimes [_ n] (reset! b 1)))
## "Elapsed time: 106.03302 msecs"

so reset!比def更快地订购级。

def creates a new atom (means allocate new memory space for an atom - setting it up - setting a pointer), while reset! just resets an existing atom (just changing value in the cell the pointer points to).
Therefore it is logical that reset! must be much cheaper (faster execution and less usage of resources) than def which you can test by:

(def n 10000000)

(time (dotimes [_ n] (def a (atom 1))))
## "Elapsed time: 2294.676443 msecs"


(def b (atom 1))
(time (dotimes [_ n] (reset! b 1)))
## "Elapsed time: 106.03302 msecs"

So reset! is one magnitude of order faster than def.

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