其他问题已经谈到了符号的许多真实方面,但我将尝试从另一个角度解释它。
符号就是名称
与大多数编程语言不同,Clojure区分事物和事物的名称。在大多数语言中,如果我说类似于var x = 1
这样的东西,那么正确且完整地说“x是1”或“x的值为1”就足以了。但是在Clojure中,如果我说(def x 1)
,我做了两件事情:我创建了一个Var(一个持有值的实体),并用符号x
命名它。在Clojure中说“x的值为1”并没有完全说明问题。更准确(虽然麻烦)的陈述应该是“由符号x命名的var的值为1”。
符号本身只是名称,而vars是持有值的实体,它们本身没有名称。如果扩展前面的例子,我说(def y x)
,我没有创建一个新的var,我只是给我的现有var起了第二个名称。这两个符号x
和y
都是相同var的名称,该var的值为1。
一个类比:我的名字是“Luke”,但那不等同于我作为一个人。这只是一个词。在某些时候,我可以改变我的名字,还有许多其他人共享我的名字。但在我的朋友圈(在您的命名空间中),单词“Luke”表示我。在幻想的Clojure世界中,我可能是一个为您携带值的var。
但为什么?
那么,为什么会有这个额外的名称概念,而不是像大多数语言那样将两者混为一谈?
首先,不是所有的符号都绑定到变量。在本地上下文中,比如函数参数或let绑定中,您代码中所指的符号引用的值实际上根本就不是变量 - 它只是一个本地绑定,在编译器处理时将被优化并转换为原始字节码。
但最重要的是,这是Clojure的“代码即数据”的哲学的一部分。代码行(def x 1)
不仅仅是一个表达式,它还是数据,具体来说是由值def
,x
和1
组成的列表。这非常重要,特别是对于操作代码数据的宏来说。
但是,如果(def x 1)
是一个列表,那么列表中的值是什么?特别是这些值的类型是什么?显然1
是一个数字。但是def
和x
呢?当我将它们作为数据进行操纵时,它们是什么类型?答案是,它们是符号。
这就是符号在Clojure中成为独立实体的主要原因。在某些上下文中,例如宏中,您想要获取名称并操作它们,使其与运行时或编译器授予的任何特定含义或绑定分离。而名称必须是某种东西,它们所代表的东西是符号。
String
会被解析为一个类。 - Alex Taggart