初學 Lisp 時一直搞不懂 atom 跟 symbol 到底差在哪…不對那個時候連 symbol 是三小都搞不清楚。不過不才在下最近突然理解了 Lisp 裡面的 Symbol 跟 Atom 的意義,所以來解釋一下。
此篇假設你已經理解 Lisp 中的 cons 與 list。
atom
atom 這個詞本來的意思就是指不可分割的東西、最小的單位,而 Lisp 中,只有 cons (或者用其他語言使用者比較可以理解的詞,叫做 list) 是可以分割的。例如最基本的 operator 之一。
其他舉凡 integer, float, symbol, string 甚至乍看之下以為可以分割的 vector 都是屬於「不可分割」的東西。
Lisp 中一切不可分割的東西,都叫做 atom。或者換句話說,list 以外的任何東西,都是 atom,因為只有 list 是可以分割的。
有個例外…就是
nil
。 這鬼東西比較機車一點,雖然它屬於 list(空的 list),但也同時屬於 atom(空的 list 確實也無法再分割啊)…
atom
這個最基本的 Lisp operator 的功能就是判斷一個物件是否為 atom:
1 | (atom 12) ; => t |
所以…在現代的 Lisp dialect 中,(atom x)
的意義基本上完全等同於 (not (consp nil))
,真是毫無屁用啊。
symbol
一個 symbol 一定屬於 atom,但 atom 不一定屬於 symbol
舉例來說,一個 integer 是個 atom,但並不屬於 symbol
1 | ;; 一個 symbol |
一個 interger 只是 atom,而不是 symbol,所以當然也沒有 symbol 該有的功能,例如 每一個 symbol 都有點像是物件導向語言中的物件,裡面包含了一些屬性,以 Common Lisp 跟 Emacs Lisp 為例,每個 symbol 都擁有如下的屬性:
屬性名稱 | 可用啥函數取出內容 | 用途 |
---|---|---|
name | symbol-name |
該 symbol 轉成字串時的樣子 |
value | symbol-value |
該 symbol 作為 variable 使用時所儲存的 |
function | symbol-function |
該 symbol 作為 function 使用時所儲存的 function 本體 |
plist | symbol-plist |
一個看你要拿來幹麻都行的 plist |
你就可以知道,為什麼一個 function 或 variable 要取名時得用 symbol 當名稱。一個整數在 Lisp 無法拿來當作 function 或 variable 的名稱,因為整數並不是 symbol。
symbol 可以想成是 C/C++ 裡的指標,每個 symbol 都指向記憶體的某個位置。所以,當你用 eq
來比較兩個 symbol 是否相同時,會比使用 equal
或 string=
來比較兩個字串速度來得快。(因為字串得一個個字元比較,而 symbol 只要比對記憶體位置)