2010-08-28 90 views
19

就範圍而言?在內存中的實際執行?語法?例如,如果(讓a 1)是'a'變量或符號?LISP中的變量和符號有什麼區別?

+0

[clisp](http://clisp.sourceforge.net/)是Common Lisp的特定實現,並且您的問題是關於語言的,所以我冒昧地改變你的標籤。 – Gilles 2010-08-28 10:54:58

回答

18

約爾格的方向是正確的答案要點。讓我補充一點。

我會談談與Common Lisp類似的Lisp。

符號爲數據結構

符號是在Lisp中真正的數據結構。您可以創建符號,您可以使用符號,可以存儲符號,可以傳遞符號,符號可以是較大數據結構的一部分,例如符號列表。一個符號有一個名字,可以有一個值並且可以有一個函數值。

所以你可以採取一個符號,並設置它的價值。

(setf (symbol-value 'foo) 42) 

通常一個會寫(setq foo 42),或(set 'foo 42)(setf foo 42)

符號代碼表示變量

但是!

(defun foo (a) 
    (setq a 42)) 

(let ((a 10)) 
    (setq a 42)) 

在這兩種形式在上面的源代碼有符號和a寫入像一個符號,並使用該函數READ來讀取源返回在一些列表中的符號a。但setq操作不會將符號值a設置爲42。這裏LETDEFUN介紹了我們用符號編寫的一個變量a。因此,SETQ操作會將變量值設置爲42

詞彙結合

所以,如果我們看一下:

(defvar foo nil) 

(defun bar (baz) 
    (setq foo 3) 
    (setq baz 3)) 

我們引入一個全局變量FOO

在酒吧中,第一個SETQ設置全局變量FOO的符號值。第二個SETQ將本地變量BAZ設置爲3。在這兩種情況下,我們都使用相同的SETQ,我們將該變量作爲符號編寫,但在第一種情況下,FOO捐獻了一個全局變量以及那些存儲值在符號值中。在第二種情況下,BAZ表示一個局部變量以及值如何存儲,我們不知道。我們所能做的就是訪問變量來獲得它的價值。在Common Lisp中,沒有辦法使用符號BAZ並獲取本地變量值。我們無法使用符號訪問局部變量綁定及其值。這是Common Lisp中局部變量的詞彙綁定的一部分。

這導致例如觀察,在沒有記錄調試信息的編譯代碼中,符號BAZ消失。它可以是處理器中的寄存器,也可以是其他方式實現的。符號FOO仍然存在,因爲我們將它用作全局變量。

符號

符號的各種用途是一種數據類型,在Lisp中的數據結構。

變量是概念性的東西。全局變量基於符號。本地詞彙變量不是。

在源代碼中,我們使用符號爲函數,類和變量編寫各種名稱。

有一些概念重疊:

(defun foo (bar) (setq bar 'baz)) 

在上面的源代碼,defunfoobarsetqbaz是所有符號。

DEFUN是提供宏的符號。 FOO是提供功能的符號。 SETQ是提供特殊操作員的符號。 BAZ是用作數據的符號。因此在BAZ之前的報價。 BAR是一個變量。在編譯的代碼中,不再需要它的符號。

4

Lisp使用環境它們與映射(鍵 - >值)類似,但具有用於鏈接環境和控制綁定的額外內置機制。現在

符號是好看多了,(除特殊形式的符號),並指向一個值,
功能整數列表
因爲常見Lisp給你一種方法來改變這些值,即用setq,在一些情況下符號
(你的例子)也是變量

9

A 符號是一個事物的名稱。 A 變量是一個可變指針,指向可變的存儲位置。

在您顯示的代碼段中,leta都是符號。在let塊的範圍內,符號a表示當前綁定到值1的變量。

但事物的名稱本身並不是事物。符號a不是一個變量。這是一個名稱的變量。但在此特定上下文中僅有。在不同的上下文中,名稱a可以指代完全不同的事物。

例:符號jaguar可根據上下文,表示

+1

對,這個答案指向了正確的方向。 – 2010-08-28 14:01:56

+0

+1在不同情況下提及符號意味着不同的事物。當試圖理解** x **和**#'x **和**'x **之間的區別時,這非常有幫助。 – Baggers 2013-01-09 15:19:56

11

Common Lisp HyperSpec報價:

symbolñ。objecttypesymbol

variablen。 a binding在「變量」namespace中。

bindingn。name名稱表示的關聯。 (...)

解釋時間。

什麼Lisp調用符號是相當接近許多語言稱爲變量。在第一次近似中,符號具有值;當您評估表達式x時,表達式的值是符號x的值;當您編寫(setq x 3)時,您將爲x指定一個新值。在Lisp術語中,(setq x 3)將值3綁定到符號x

大多數語言沒有的Lisp功能是符號是普通對象(符號是編程語言術語中的第一類對象)。當您編寫(setq x y)時,x的值將變爲分配時的值y。但你可以寫(setq x 'y),在這種情況下x的值是y

從概念上講,有一個environment它是從符號到值的關聯表。評估符號意味着在當前環境中查找它。 (環境也是一流的對象,但這超出了本答案的範圍。)綁定引用了環境中的特定條目。但是,還有一個額外的複雜因素。

大多數Lisp方言都有多個名稱空間,至少包含變量名稱空間和函數名稱空間。一個環境實際上可以包含一個符號的多個條目,每個名稱空間包含一個條目。嚴格來說,變量是變量的名稱空間中的環境條目。在日常的Lisp術語中,當其作爲變量的綁定作爲變量時,通常將符號稱爲變量。

例如,在(setq a 1)(let ((a 1)) ...),a是符號。但是由於構造對符號a的變量綁定起作用,所以通常在此上下文中將a作爲變量。

在另一方面,在(defun a (...) ...)(flet ((a (x) ...)) ...)a是一個象徵也是,但這些結構作用於它的功能結合,所以a不會被認爲是一個變量。

在大多數情況下,當一個符號在表達式中不加引號時,通過查找其變量綁定來評估它。主要例外是在函數調用(foo arg1 arg2 ...)中,使用了foo的函數綁定。引用的符號'x(quote x)的值本身就像任何引用的表達式一樣。當然,也有大量的特殊形式,你不需要引用一個符號,包括setqletfletdefun

1

符號和變量是兩個不同的東西。 像數學符號一樣是一個值。和變量在數學上有相同的含義。

但是你的困惑來自這樣一個事實,即符號是變量的元表示。

如果你

(setq a 42) 

也就是說你只要定義一個變量。順便提一下,常見的lisp存儲方式是拋出符號的結構。

在普通的嘴脣符號是一個具有不同屬性的結構。每一個可以與像symbol-namesymbol-function函數訪問...

在變量的情況下,你可以通過S訪問他的價值symbol-value

? (symbol-value 'a) 
42 

這是沒有得到的值的常見情況。

? a 
42 

注意,符號是自我評估是否意味着,如果你問一個符號,你得到的符號不是symbol-value

? 'a 
A 
2

符號是一個Lisp數據對象。 Lisp「表單」意味着要進行評估的Lisp對象。當一個符號本身被用作Lisp表單時,即當你評估一個符號時,結果是一個與該符號相關聯的值。值與符號相關聯的方式是Lisp語言的深層部分。該符號是否已被宣佈爲「特殊」或極大地改變了評估的工作方式。

詞法值用符號表示,但不能將這些符號作爲對象自己操作。在我看來,用「指針」或「位置」來解釋Lisp中的任何內容都不是最好的方法。

1

添加一個側面說明上述答案:

新人爲Lisp往往不知道到底是什麼符號是,除了作爲變量的名字。我認爲最好的答案是,它們就像枚舉常量,除了在使用它們之前不必聲明它們。當然,正如其他人所解釋的那樣,它們也是對象。 (這對Java用戶來說似乎並不陌生,其中枚舉常量也是對象。)

相關問題