clojure中符号symbols 和变量vars的正确理解
原地址 http://stackoverflow.com/questions/11662084/why-does-clojure-distinguish-between-symbols-and-vars?rq=1
Symbols are names
Unlike most programming languages, Clojure makes a distinction between things and the names of things. In most languages, if I say something like var x = 1
, then it is correct and complete to say "x is 1" or "the value of x is 1". But in Clojure, if I say (def x 1)
, I've done two things: I've created a Var (a value-holding entity), and I've named it with the symbol x
. Saying "the value of x is 1" doesn't quite tell the whole story in Clojure. A more accurate (although cumbersome) statement would be "the value of the var named by the symbol x is 1".
Symbols themselves are just names, while vars are the value-carrying entities and don't themselves have names. If extend the earlier example and say (def y x)
, I haven't created a new var, I've just given my existing var a second name. The two symbols x
and y
are both names for the same var, which has the value of 1.
An analogy: my name is "Luke", but that isn't identical with me, with who I am as a person. It's just a word. It's not impossible that at some point I could change my name, and there are many other people that share my name. But in the context of my circle of friends (in my namespace, if you will), the word "Luke" means me. And in a fantasy Clojure-land, I could be a var carrying around a value for you.
But why?
So why this extra concept of names as distinct from variables, rather than conflating the two as most languages do?
For one thing, not all symbols are bound to vars. In local contexts, such as function arguments or let bindings, the value referred to by a symbol in your code isn't actually a var at all - it's just a local binding that will be optimized away and transformed to raw bytecode when it hits the compiler.
Most importantly, though, it's part of Clojure's "code is data" philosophy. The line of code (def x 1)
isn't just an expression, it's also data, specifically a list consisting of the values def
, x
, and 1
. This is very important, particularly for macros, which manipulate code as data.
But if (def x 1)
is a list, than what are the values in the list? And particularly, what are the types of those values? Obviously 1
is a number. But what about def
and x
? What is their type, when I'm manipulating them as data? The answer, of course, symbols.
And that is the main reason symbols are a distinct entity in Clojure. In some contexts, such as macros, you want to take names and manipulate them, divorced from any particular meaning or binding granted by the runtime or the compiler. And the names must be some sort of thing, and the sort of thing they are is symbols.
翻译
和大多数编程语言不同,clojure在事物和事物的名字上有区别,在大多数语言里,例如js中 如果定义 var x = 1,正确,完整的说,x是1 ,或者说x的值是1
但是在clojure中,我这么定义 (def x 1),我做了2件事,创造了一个var就是变量,并且用符号x 给这个变量var起了名字,在clojure中说x的值是1并不十分准确
更准确的说法是, 一个变量,它的名字是符号x 它的值是1
符号本身仅仅是个名字,当变量绑定某个值或者元素时,他们本身没有名字,把刚才(def x 1),这个扩展一下,这么写 (def y x),意思是。我没有创建新的变量 我仅仅是给存在的变量起了第二个名字 ,两个符号 x 和y 都是一个变量的名字 变量的值是1
打个比方 我的名字是 Luke ,但那不完全等同于我这个人,仅仅是一个词,我可以改名字,也有许多人叫这个名字,但是在我的朋友圈中,大家都懂这个词就说的是我,
在clojure的世界。我可以作为一个变量var为你存储或者绑定值
为什么要这么处理
为什么要给变量取额外的名字,而不是像大多数语言一样放在一起
一个原因是。不是所有的符号都是变量 在对应的上下文中,例如函数参数,或者let绑定形式,在你的代码中这些值通过符号引用,根本不是一个变量,仅仅是一个本地绑定
被优化和转换成字节流,在编译时
更重要的是在clojure中,代码就是数据 的哲学理念 这行代码 (def x 1) 不仅仅是一个表达式,也是数据 ,他是由def ,x, 1 组成的列表结构,这个非常重要,特别是对于将代码作为数据的宏来说
但是如果 (def x 1)是一个列表,那么,列表中的值是什么呢,就是说。这些值是什么类型,明显1 是数字类型,那么def 和x呢,当我把他们当作数据操作时。他们是什么类型? 答案是 符号 类型
这就是符号在clojure中这么独特的主要原因,在特定的上下文中,例如 宏,你想给他们起名并操作他们,脱离任何实际意思或通过编译器绑定授权,这些名字必须是某种类型。这些类型就是符号