了解clojure中的var



我对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"表单返回一个名为#'用户/水果的新的var数据结构?
  2. 似乎符号'水果在每种" def"形式之后与不同的var绑定 - 这是因为代表绑定的任何结构都是可变的数据结构吗?

在您的第一个问题上:不,它实际上是更改var水果中包含的值,而不是制作新的值:

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

如果我们保存对水果的引用var(#'是用于引用VAR本身的简写,而不是其内容),则重新定义它,identical?函数告诉我们,这些是 same same same 对象。

对于第二个问题:名称空间是可突变的数据结构,将符号映射到vars 。从某种意义上说,它们的其余数据结构都在原处,并且已更新到位,它们并不持久。值得注意的是,var和名称空间完全不同。虽然名称空间提供名称查找,并且通常将名称解析到vars中,但他们自己与var无关。您可以将VAR存储在您想要的任何东西中,并且严格来说,不得不使用名称空间来跟踪您的VAR。VAR还提供了比命名空间(或至少不同功能)更多的功能。它们具有每个线程绑定,因此您可以在一个线程上安全地 bind a var到一个新值,而不会影响其他线程。

来自文档:

名称空间:

名称空间是从简单(不合格的)符号到var和/或类的映射。VAR可以使用def或其任何变体在命名空间中实施,在这种情况下,它们具有一个简单的名称符号和对包含名称空间的引用,以及符号为同一var的名称空间映射。

vars:

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

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

当您评估一些包含您所定义的VAR的符号(假设其没有任何局部词汇绑定)时,编译器首先查找映射到该符号的VAR,然后获取当前值为此,

最新更新