2009-10-06 35 views
111

我有一個從其他Lisp(特別是Scheme)通過的知識。最近我一直在閱讀關於Clojure。我看到它有「符號」和「關鍵字」。我熟悉的符號,但不包含關鍵字。爲什麼Clojure除了「符號」還有「關鍵字」?

其他Lisps有關鍵字嗎?除了具有不同的符號(即:冒號)之外,關鍵字與符號有什麼不同?

+0

參見:[Clojure中,爲什麼有一個字符串,關鍵詞和符號?(http://stackoverflow.com/q/11655080/405550) – Zaz 2016-07-29 08:09:57

回答

119

以下是關鍵字和符號的Clojure documentation

關鍵字是評估自己的符號標識符。它們提供非常快速的相等性測試...

符號是通常用於引用其他內容的標識符。它們可以在程序形式中用來指函數參數,允許綁定,類名和全局變量...

關鍵字通常用作輕量級的「常量字符串」,例如,用於哈希映射的鍵或多方法的分派值。符號通常用於命名變量和函數,並且除了在宏等中直接操作它們作爲對象操作它們是不常見的。但是沒有任何東西阻止你在使用關鍵字的任何地方使用符號(如果你不介意的話)。

查看差異的最簡單方法是在Clojure源文件中讀取Keyword.javaSymbol.java。有一些明顯的實施差異。例如,Clojure中的Symbol可以具有元數據,並且關鍵字不能。

除了單冒號語法之外,還可以使用雙冒號生成限定名稱空間的關鍵字。

user> :foo 
:foo 
user> ::foo 
:user/foo 

Common Lisp具有關鍵字,就像Ruby和其他語言一樣。當然,它們在這些語言中略有不同。 Common Lisp關鍵字和Clojure關鍵字之間的一些區別:

  1. Clojure中的關鍵字不是符號。

    user> (symbol? :foo) 
    false 
    
  2. 關鍵詞不屬於任何命名空間,除非您特別限定它們:(感謝Rainer Joswig給我的東西的想法來看待)

    user> (namespace :foo) 
    nil 
    user> (namespace ::foo) 
    "user" 
    

+9

這解釋了不同之處,但不是爲什麼需要兩種不同的構造。難道Clojure已經通過關鍵字和符號的能力結合創造了一些東西? – mtnygard 2009-10-16 19:57:39

+20

關鍵字是輕量級的,並有一個方便的語法,我認爲這是關於它的一切。如果沒有它們,這種語言就能正常工作,但它們很好用,而且它們被廣泛使用。由於關鍵字總是自我評估(即不能將它們用作變量或函數名稱),並且一般情況下的符號不能總是自我評估,所以不能將它們的能力結合起來。 – 2009-10-16 20:44:38

+1

似乎關鍵字作爲hashmaps等中的關鍵字更有用,因爲它們一旦被評估就不會改變:'(eval(eval':a))'vs'(eval(eval''a))'。還有其他優點嗎?性能方面,它們是相同的? – kristianlm 2012-08-03 19:56:10

5

關鍵字是自我評估的符號,因此您不必記住引用它們。

+5

是不是這樣?打字:而不是'看起來不是什麼大贏,尤其是因爲:在大多數鍵盤上是一個額外的按鍵。 – 2009-10-06 19:29:13

+8

嗯,它不僅僅是人物,真的。關鍵詞在評估之後保留關鍵字,而符號則根據其綁定的內容進行評估。它更像是一種語義差異,因爲它們通常用於不同的目的。 – 2009-10-06 19:41:31

+12

關鍵字在Clojure中不是符號 – 2010-11-17 02:34:38

26

Common Lisp包含關鍵字符號。

關鍵字也是符號。

(symbolp ':foo) -> T 

是什麼讓特殊的關鍵字:

  • :FOO是由Common Lisp的讀者爲標誌的關鍵字:: foo的
  • 關鍵字評估自己解析:FOO - >:FOO
  • 關鍵字符號的home包是KEYWORD包:關鍵字:foo - >:foo
  • 關鍵字從包中導出KEYWORD
  • 關鍵字是常量,不允許分配不同的值

否則關鍵字是普通符號。所以關鍵字可以命名函數或具有屬性列表。

切記:Common Lisp符號屬於一個包。這可以寫成:

  • FOO,當符號是當前包訪問
  • 富:酒吧,當符號FOO從包裝BAR出口
  • :: foo的酒吧,當符號FOO在包BAR中

對於關鍵字符號表示:foo,關鍵字:foo和關鍵字:: foo都是相同的符號。因此通常不使用後兩個符號。

所以:foo只是被解析到包KEYWORD中,假設在符號名稱之前沒有給出包名,這意味着默認情況下包含KEYWORD包。

2

:關鍵字也被許多集合特別對待,允許一些非常方便的語法。

(:user-id (get-users-map)) 

相同

((get-users-map) :user-id) 

這使得事情只是一個小更flexable

+19

這也適用於符號,('a {'a 1'b 2})=> 1和({'a 1'b 2}'b)=> 2。 – Jonas 2009-10-07 02:28:57

3

對於關鍵字,哈希值計算和緩存的關鍵字時, 首先構建。當查找關鍵字作爲散列鍵時,它只是 返回預先計算的散列值。對於字符串和符號,在每次查找時重新計算散列值 。

爲什麼相同的命名關鍵字總是相同的,它們包含它們自己的散列值。 由於搜索的地圖和集合是由散列鍵組成的,因此這種搜索效率在搜索次數較多的情況下具有更高的搜索效率,而不是搜索本身。

相關問題