【问题标题】:Understanding vars in Clojure了解 Clojure 中的变量
【发布时间】:2014-01-27 17:55:37
【问题描述】:

我是 Clojure 的新手,我很难理解使用以下代码在幕后发生的事情:

; Associate the symbol 'fruits to the value ["apple" "banana"]
(def fruits ["apple" "banana"]) ; returns the var #'user/fruits
(count fruits) ; returns 2

(def fruits ["cherry" "orange" "grapes"]) ; returns the var #'user/fruits
(count fruits) ; returns 3
  1. 每个“def”表单是否返回一个名为 #'user/fruits 的新 var 数据结构?
  2. 似乎符号 'fruits 在每个“def”形式之后都绑定到不同的 var - 这是因为表示绑定的任何结构都是可变数据结构吗?

【问题讨论】:

    标签: data-structures clojure immutability


    【解决方案1】:

    对于您的第一个问题:不,实际上是在更改 Var 水果中包含的值,而不是创建一个新值:

     user> (let [old-fruits #'fruits] 
             (def fruits ["cherry" "orange" "grapes"]) 
             (identical? old-fruits #'fruits))
    true
    

    如果我们保存对水果 Var 的引用(#' 是引用 Var 本身的简写,而不是其内容)然后重新定义它,identical? 函数告诉我们这些是相同目的。

    对于第二个问题:命名空间是一种将符号映射到变量的可变数据结构。它们不是持久的,因为 Clojure 的数据结构的其余部分是并且在原地更新的。值得注意的是,变量和命名空间是完全不同的东西。虽然命名空间提供名称查找并通常将名称解析为 var,但它们本身与 var 几乎没有关系。您可以将 var 存储在任何您想要的地方,严格来说,您不必使用命名空间来跟踪您的 var。 Vars 还提供比命名空间更多的功能(或至少不同的功能)。它们具有每个线程的绑定,因此您可以在一个线程上安全地将 var bind 一个新值,而不会影响其他线程的更改。

    【讨论】:

    • 我认为最后一段有点误导 - 重新设置 Var 的根绑定不会改变命名空间映射。
    • 难道说var和代表命名空间绑定的数据结构都是可变数据结构吗?
    • 是的,尽管 var 提供了每个线程的更改,而命名空间不提供。我将编辑最后一段以使这种区别更加清晰,并通过设置 vars 的根值删除关于不编程的句子。这真的不属于关于名称空间的段落。再次感谢您的反馈
    【解决方案2】:

    来自文档:

    Namespaces

    命名空间是从简单(非限定)符号到变量和/或类的映射。 var 可以使用 def 或其任何变体在命名空间中进行实习,在这种情况下,它们有一个简单的名称符号和对其包含命名空间的引用,并且命名空间将该符号映射到同一个 var。

    Vars:

    Var 提供了一种机制来引用可变存储位置,该可变存储位置可以在每个线程的基础上动态反弹(到新的存储位置)。

    因此,命名空间和变量都是可变的。在您给出的示例中,def 的第一次出现创建了一个新的 Var 并将其实习生(即向其添加新映射)在当前命名空间中。第二次出现 def 会重置现有 Var 的根绑定,而不更改命名空间映射。

    当您评估一些包含您定义的 var 符号的代码时(假设它没有被任何本地词法绑定遮蔽),编译器首先查找映射到该符号的 var,然后获取当前值对于那个变量。

    【讨论】:

    • 感谢您的回复 - 只是为了确认一下,当您说“重置现有 Var 的根绑定”时,您的意思是 Var 现在指向新的 fruits 向量,对吗?换句话说,Var 发生了变异,现在绑定到不同的数据集,对吧?
    • 正确。正如 Arthur 指出的那样,这种可变性会影响程序的全局状态这一事实意味着您不应该使用 def 来更改 Var 根绑定,除非您第一次初始化命名空间。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-07-23
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多