为什么 Clojure 允许我重新定义同一个变量?

发布于 2025-01-11 20:46:13 字数 297 浏览 3 评论 0原文

如果变量在 Clojure 中是不可变的,那么为什么它允许在下面的代码片段中重新定义相同的变量:

(ns tutorial.test-immutability-of-variables)

(defn test_if_variables_are_mutable
  []
  (def a 1)
  (def a 10)
  (println (format "Value of a: %d" a) )
  )

(test_if_variables_are_mutable)

上面的代码编译并且 o/p 是 10。

If the variables are immutable in Clojure, then why did it allow to redefine the same variable in the following snippet:

(ns tutorial.test-immutability-of-variables)

(defn test_if_variables_are_mutable
  []
  (def a 1)
  (def a 10)
  (println (format "Value of a: %d" a) )
  )

(test_if_variables_are_mutable)

The above code compiles and o/p is 10.

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

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

发布评论

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

评论(2

苹果你个爱泡泡 2025-01-18 20:46:13

Clojure 区分对值的引用。 Clojure 保证是不可变的。

考虑一下当你的函数被求值时会发生什么:

(def a 1)

当上面的形式被求值时,会创建一个 Clojure Var(名称为 a 和命名空间 tutorial.test-immutability-of-variables ) 并且它绑定到值 1。

(def a 10)

当计算此形式时,现有的 Clojure Var 会反弹到值 10。

强烈建议不要在函数中使用 def。仅在代码中对顶级表单使用 def。或者,对于词法绑定符号,请使用 let

所发生的事情的完整情况比我上面概述的要复杂一些,请参阅参考文档在瓦尔斯上。 Clojure 中还有其他引用类型,例如 Atoms

Clojure makes a distinction between values and references to values. Clojure guarantees that values are immutable.

Consider what happens when your function is evaluated:

(def a 1)

When the above form is evaluated, a Clojure Var is created (with name a and namespace tutorial.test-immutability-of-variables) and it is bound to the value 1.

(def a 10)

When this form is evaluated, the existing Clojure Var is rebound to the value 10.

Use of def within a function is strongly discouraged. Use def for top level forms only in your code. Alternatively for a lexically bound symbol use let.

The full story of what happens is a bit more involved than I've outlined above, see the reference documentation on Vars. There are other reference types in Clojure, such as Atoms.

错爱 2025-01-18 20:46:13

正如另一个答案指出的那样,您可以更改全局 Var 指向的内容,但无法更改原始。这是另一个示例:


(def x 42)

(defn changer-1
  []
  (println "changer-1: x - old" x)
  (let [x "Goodbye"] ; change a local variable
    (println "changer-1: x - new" x)))

(defn caller-1
  []
  (newline)
  (let [x "Hello"]
    (println "caller-1: x - before" x)
    (changer-1)
    (println "caller-1: x - after " x)))

(defn changer-2
  []
  (println "changer-2: x - old" x)
  (def x 666) ; reset the global Var (normally bad form)
  (println "changer-2: x - new" x))

(defn caller-2
  []
  (newline)
  (println "caller-2: Var x - before" x)
  (let [x "Hello"]
    (println "caller-2: x - before" x)
    (changer-2)
    (println "caller-2: x - after " x))
  (println "caller-2: Var x - after" x))


(caller-1)
(caller-2)

有关结果的

-----------------------------------
   Clojure 1.10.3    Java 15.0.2
-----------------------------------

caller-1: x - before Hello
changer-1: x - old 42
changer-1: x - new Goodbye
caller-1: x - after  Hello

caller-2: Var x - before 42
caller-2: x - before Hello
changer-2: x - old 42
changer-2: x - new 666
caller-2: x - after  Hello
caller-2: Var x - after 666

更多信息,请参阅此文档列表 来源,特别是“Getting Clojure”和“Brave Clojure”

As the other answer points out, you can change what the global Var points to, but you cannot change the original value. Here is another example:


(def x 42)

(defn changer-1
  []
  (println "changer-1: x - old" x)
  (let [x "Goodbye"] ; change a local variable
    (println "changer-1: x - new" x)))

(defn caller-1
  []
  (newline)
  (let [x "Hello"]
    (println "caller-1: x - before" x)
    (changer-1)
    (println "caller-1: x - after " x)))

(defn changer-2
  []
  (println "changer-2: x - old" x)
  (def x 666) ; reset the global Var (normally bad form)
  (println "changer-2: x - new" x))

(defn caller-2
  []
  (newline)
  (println "caller-2: Var x - before" x)
  (let [x "Hello"]
    (println "caller-2: x - before" x)
    (changer-2)
    (println "caller-2: x - after " x))
  (println "caller-2: Var x - after" x))


(caller-1)
(caller-2)

with result

-----------------------------------
   Clojure 1.10.3    Java 15.0.2
-----------------------------------

caller-1: x - before Hello
changer-1: x - old 42
changer-1: x - new Goodbye
caller-1: x - after  Hello

caller-2: Var x - before 42
caller-2: x - before Hello
changer-2: x - old 42
changer-2: x - new 666
caller-2: x - after  Hello
caller-2: Var x - after 666

For more information, please see this list of documentation sources, especially "Getting Clojure" and "Brave Clojure"

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