其他问题涉及符号的许多真实方面,但我会尝试从另一个角度解释它。
符号是名称
与大多数编程语言不同,Clojure 区分事物和事物的名称。在大多数语言中,如果我说类似 的话var x = 1
,那么说“x 为 1”或“x 的值为 1”是正确且完整的。但是在 Clojure 中,如果我说(def x 1)
,我已经做了两件事:我创建了一个 Var(一个价值持有实体),并且我用符号 来命名x
它。说“x 的值为 1”并不能说明 Clojure 的全部内容。一个更准确(虽然很麻烦)的陈述是“由符号 x 命名的 var 的值是 1”。
符号本身只是名称,而 vars 是承载值的实体,它们本身没有名称。如果扩展前面的示例并说(def y x)
,我还没有创建一个新的 var,我只是给了我现有的 var 一个第二个名字。这两个符号x
和y
都是同一个 var 的名称,其值为 1。
一个类比:我的名字是“卢克”,但这与我不同,与我作为一个人的身份不同。这只是一个词。在某个时候我可以更改我的名字并非不可能,而且还有很多其他人共享我的名字。但是在我的朋友圈中(在我的命名空间中,如果你愿意的话),“Luke”这个词的意思是我。在幻想的 Clojure 领域,我可以成为一个为你带来价值的 var。
但为什么?
那么为什么这个额外的名称概念不同于变量,而不是像大多数语言那样将两者混为一谈呢?
一方面,并非所有符号都绑定到变量。在本地上下文中,例如函数参数或 let 绑定,代码中符号引用的值实际上根本不是 var - 它只是一个本地绑定,当它遇到编译器。
不过,最重要的是,它是 Clojure “代码即数据”理念的一部分。这行代码(def x 1)
不仅仅是一个表达式,它也是一个数据,特别是一个由值def
、x
和组成的列表1
。这非常重要,特别是对于将代码作为数据进行操作的宏。
但是如果 (def x 1)
是一个列表,那么列表中的值是什么?特别是,这些值的类型是什么?显然1
是一个数字。但是def
和x
呢?当我将它们作为数据进行操作时,它们的类型是什么?答案当然是符号。
这就是符号在 Clojure 中是一个独特实体的主要原因。在某些情况下,例如宏,您希望获取名称并对其进行操作,与运行时或编译器授予的任何特定含义或绑定分离。名字一定是某种东西,它们是某种东西,就是符号。