2011-04-12 32 views
1

簡要說明。這是我嘗試在clisp中實習並使用符號的幾次嘗試。我在LISP中錯過了一些關於實習符號的重要事實嗎?

[1]> (setq sym (intern "foo")) 
|foo| 
[2]> (eq sym 'foo) 
NIL 

爲什麼?

[3]> (defun internup (me &optional (package *package*)) 
    (intern (string-upcase me) package)) 
INTERNUP 

[4]> (eq 'abc (internup "abc")) 
T 

可能必須保持正常。

[12]>(let ((abc 2)) 
    (eval '(+ 2 abc))) 

*** - EVAL: variable ABC has no value 
The following restarts are available: 

確定

[18]> (let ((abc 2)) 
(eval '(+ 2 'abc))) 

*** - +: ABC is not a number 
The following restarts are available: 

有趣。我應該把它放在之前。

[14]> (setq a (internup "abc")) 
ABC 

[15]> (let ((abc 2)) 
(eval '(+ 2 a))) 

*** - +: ABC is not a number 
The following restarts are available: 

再次錯誤。嗯,我必須錯過一些有關在LISP中實習符號的重要事實。你可以幫我嗎 ?

+0

'(setf(symbol-value a)2)'w把'ABC'設置爲'2'。 – khachik 2011-04-12 17:20:45

回答

3

您的問題與實習無關。

第一個問題的確是由於讀者總是使用大寫符號,所以您需要調用(實習生「FOO」)才能獲得與「foo」相同的結果。

EVAL的問題是由於LET引入了EVAL內部不可見的詞彙綁定。如果你真的想這個工作,你不得不宣告ABC是特殊的,就像這樣:

(let ((abc 2)) 
    (declare (special abc)) 
    (eval '(1+ abc))) 

特別聲明將導致變量擁有動態綁定,而不是詞彙的結合(後者指綁定僅限於局部詞法環境,即在LET表單中,通過特殊聲明,該變量可用於從該表單調用的任何內容)。

請注意,使用特殊聲明和eval是您應該非常小心的事情,您應該首先重新考慮您對EVAL的使用。你真的需要使用它是非常罕見的。在大多數情況下,您實際上正在尋找使用lambda函數。

+0

非常感謝。但是,使用lambda函數的意思是什麼。我從事數學符號評估,我無法想象與調用eval函數不同的方法。 (eval(diff(make-equation database)'x)) – Cernydav 2011-04-12 21:24:54

+0

EVAL將在空詞彙環境中評估表達式。 LET(通常)建立詞彙綁定。因此,要從EVAL訪問變量,它必須是一個動態綁定,因此需要爲該綁定指定一個SPECIAl聲明或由DEFVAR或DEFPARAMETER建立一個聲明。 – Vatine 2011-04-13 13:01:31

3

Eval評估空詞彙環境中的表格,即沒有詞彙綁定。這與符號的實習無關。

2

的Common Lisp的閱讀器的情況下,靈敏度由readtable確定:

(readtable-case *readtable*) 

典型地,讀取器將在最初大寫實習生符號(除非明確轉義字符)。因此:

(eq (intern "foo") 'foo) => NIL

(eq (intern "FOO") 'foo) => T

(eq (intern "FOo") 'fo\o) => T

可以使用反引號語法來建立EVAL形式:

(let ((abc 2)) 
    (eval `(+ 2 ,abc))) 

= > 4

+0

只是爲了澄清:反引用形式相當於'(list(quote +)(quote 2)abc)',它的計算結果是_list_'(+ 2 2)',然後傳遞給'eval'。明確的'eval'調用永遠不會看到變量'abc'。 – Svante 2011-04-13 16:10:16