我看到了this question已经,但这并不能解释我的疑惑。
当我刚从Common Lisp 来到Clojure 时,我很疑惑为什么它把符号和关键字作为单独的类型来对待,但后来我想通了,现在我觉得这是一个绝妙的想法。现在我想弄清楚为什么符号和变量是不同的对象。
据我所知,Common Lisp 实现通常使用结构表示“符号”,该结构具有 1) 名称字符串,2) 在函数调用位置求值时指向符号值的指针,3) 指向外部调用位置评估时的值,以及 4) 属性列表等。
忽略 Lisp-1/Lisp-2 的区别,事实仍然是在 CL 中,“符号”对象直接指向它的值。换句话说,CL 将 Clojure 所称的“symbol”和“var”组合在一个对象中。
在 Clojure 中,要计算一个符号,首先必须查找相应的 var,然后必须取消引用 var。为什么 Clojure 以这种方式工作?这样的设计可能有什么好处?我知道 var 具有某些特殊属性(它们可以是私有(private)的、常量的或动态的...),但这些属性不能简单地应用于符号本身吗?
最佳答案
其他问题涉及符号的许多真实方面,但我会尝试从另一个角度解释它。
符号就是名字
与大多数编程语言不同,Clojure 区分事物 和事物的名称。在大多数语言中,如果我说类似 var x = 1
的内容,那么说“x 是 1”或“x 的值是 1”是正确且完整的。但在 Clojure 中,如果我说 (def x 1)
,我做了两事:我创建了一个 Var(一个值持有实体),并且我用符号 x
为它命名。说“x 的值为 1”并不能完全说明 Clojure 中的全部情况。更准确(虽然麻烦)的说法是“由符号 x 命名的 var 的值为 1”。
Symbols 本身只是名称,而 vars 是承载值的实体,本身没有名称。如果扩展前面的示例并说 (def y x)
,我还没有创建新的 var,我只是给现有的 var 起了第二个名字。 x
和 y
这两个符号都是同一个 var 的名称,其值为 1。
打个比方:我的名字是“卢克”,但这与我本人不同,与我这个人不同。这只是一个词。在某些时候我可以更改我的名字并非不可能,而且还有很多其他人与我同名。但在我的 friend 圈中(如果你愿意,在我的命名空间中),“卢克”这个词意味着我。在幻想的 Clojure 世界中,我可以是一个为你携带值(value)的 var。
但为什么呢?
那么为什么这个额外的名称概念与变量不同,而不是像大多数语言那样将两者混为一谈?
一方面,并非所有符号都绑定(bind)到变量。在局部上下文中,例如函数参数或 let 绑定(bind),代码中符号引用的值实际上根本不是 var - 它只是一个局部绑定(bind),当它遇到编译器。
不过,最重要的是,它是 Clojure 的“代码就是数据”理念的一部分。这行代码 (def x 1)
不仅仅是一个表达式,它还是数据,特别是一个由值 def
、x
和 1
。这非常重要,尤其是对于将代码作为数据进行操作的宏而言。
但是如果 (def x 1)
是一个列表,那么列表中的值是多少?特别是,这些值的类型是什么?显然 1
是一个数字。但是 def
和 x
呢?当我将它们作为数据进行操作时,它们的类型是什么?答案当然是符号。
这就是符号在 Clojure 中是一个独特实体的主要原因。在某些上下文中,例如宏,您想要获取名称并对其进行操作,脱离运行时或编译器授予的任何特定含义或绑定(bind)。名称必须是某种东西,而它们就是符号。
关于clojure - 为什么 Clojure 区分符号和变量?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11662084/