2014-03-02 170 views
1

我很想知道爲什麼set似乎是唯一的原因。例如:爲什麼SET不推薦使用?

(set 'nm 3) ;; set evaluates its first argument, a symbol, has to be quoted 
    nm ;; ==> evaluates to 3 
    (set 'nm 'nn) ;; assigns nn to the value cell of nm 
    nm ;; ==> evaluates to nn 
    nn ;; ==> ERROR. no value 
    (set nm 3) ;; since nm evaluates to nn ... 
    nm ;; evaluates to nn 
    nn ;; evaluates to 3 

實現類似的行爲,我只能夠使用setf

(setq tu 'ty) ;; 
    (symbol-value 'tu) ;; returns ty 
    (setq (symbol-value 'tu) 5) ;; ERROR. setq expects a symbol 
    (setf (symbol-value tu) 5) ;; has to be unquoted to access the value cell 
    tu ;; ==> evaluates to ty 
    ty ;; ==> evaluates to 3 

在其他編程語言爲降級的理由(一個或多個)是相當清楚的:效率低下,錯誤容易或不安全的想到。我想知道當時set的折舊標準是什麼。我能從網上收集到的是this,這是可笑的。謝謝。

回答

2

主要原因set已棄用的是,它的使用可能會導致錯誤的時候它是在約束變量使用(例如,在功能):

(set 'a 10) 
==> 10 
a 
==> 10 
(let ((a 1)) ; new lexical binding 
    (set 'a 15) ; modification of the value slot of the global symbol, not the lexical variable 
    a)   ; access the lexical variable 
==> 1   ; nope, not 15! 
a 
==> 15 

set是從當Lisp的是次傳統功能「符號和列表的語言」。從那時起,Lisp已經成熟了;符號插槽上的直接操作比較少見,並且沒有理由使用set而不是更明確的(setf symbol-value)

+0

是否有任何資源指定這種事情的細節?必須有文件的地方... – macrolyte

0

在您的例子:

(set nm 'nn) ;; assigns nn to the value cell of nm 
nm ;; ==> evaluates to nn 

這是完全錯誤的,爲什麼它棄用的主要原因。這是您在評估nm時得到的符號,與nn綁定。不幸的是,在您的示例中,數字爲3,並且它將在運行時發出錯誤信號,因爲您不能將數字用作變量。如果您要編寫(setq 3 'nn),則可以在編譯時查看錯誤。

使用set還有一個額外的原因。當你不知道要綁定什麼符號並且編譯器無法優化它時,編譯起來非常困難。

Scheme在它的第一個版本中沒有自動引用,他們甚至沒有像setq這樣的引用宏。相反,它表示set'就足夠了。很明顯,它不是因爲Scheme不再有set而只有define

我個人不同意它應該被刪除(最終棄用會導致刪除),但像eval它應該被避免並且只能作爲最後的手段使用。

+0

謝謝,這只是一個壞小狗似乎無害。看起來像奧萊耶拉需要放下... – macrolyte

相關問題