为什么我可以在 Clojure 中更改不可变变量?

Why can I change immutable variables in Clojure?

我来自 Javascript 世界,那里使用 const 来声明不可变变量。

不可变变量的定义在 Clojure 中以相同的方式解释。

但是,这是允许的:

(def cheese "I like cheese")

...
...

(def cheese "Actually, I changed my mind)

当我 运行 这个时,repl 给了我 actually, I changed my mind

在JS中会报错,因为aconst不能改

如果有人能解释一下我对 immutable variables 在 clojure 世界中的理解不正确的地方,我将不胜感激?

谢谢

准确地说,Clojure 有不可变值,而不是不可变变量。毕竟,名称 Var 是 shorthand 的“变量”。

想象一下这个数字 5。你永远不需要担心谁“拥有”它,或者有人可能会改变它的定义。此外,在您的程序的许多部分中,可以有多个用于多种用途的该编号的多个副本。 Clojure 将这个想法扩展到集合值,例如向量 [1 2 3] 或映射 {:first "Joe" :last "Cool"}.

话虽如此,在 Clojure 中,Var 通常用于永远不会更改(尽管它可以)的全局“常量”值。对于确实发生变化的值,使用 Clojure Atom(全局或局部)是正常的。还有许多其他选项(例如 reduce 等函数有一个内部累加器)。

list of documentation sources 是一个很好的起点,尤其是“Getting Clojure”和“Brave Clojure”两本书。

正如 Alan 提到的,Clojure 具有不可变的值,而不是不可变的变量。

当你执行

(def x 42)

创建了一个 Clojure Var,Var 绑定到名称(又名符号)x,并且不可变值 42 被放置在 Var 中. Var 是值的容器。通常,一个 Var 中只会放置一个值。但是,在您的示例中,在不同时间 Var 中可以放置不同的不可变值。

阅读 Clojure Vars and the Global Environment 可能会有帮助。