原地址 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中這麼獨特的主要原因,在特定的上下文中,例如 巨集,你想給他們起名並操作他們,脫離任何實際意思或通過編譯器繫結授權,這些名字必須是某種型別。這些型別就是符號