2012-03-21 37 views
3

如何檢查變量是否在let構造之前定義?Elisp:bounds in let

(let (((if (boundp 'a) 
      'a 
     'dummy) t)) 
    (message "I made this work")) 

我所試圖做的是檢查是否如果它已經,將其綁定到本地ta前界。否則根本不在乎a

回答

5

的代碼失敗:(wrong-type-argument symbolp (if (boundp (quote a)) (quote a) (quote dummy))),表明let特殊形式*不計算這樣的說法(儘管該列表將評估爲一個符號,列表本身不是一個符號)。

這是一個簡單但有缺陷的替代方法,它爲a創建一個本地綁定,但是如果它本來是未綁定的,則將其解除綁定到本地範圍。

(let ((a (if (boundp 'a) t nil))) 
    (or a (makunbound 'a)) 
    ;; do things 
) 

的缺陷是,如果a最初是未綁定的,你想的是本地範圍內的分配a活得比局部範圍,它不會使用這種方法。

起初,我想你需要放棄let完全避開這個問題,只是用這樣的:

(when (boundp 'a) 
    (setq a-backup a 
     a t)) 
;; do things 
(when (boundp 'a-backup) 
    (setq a a-backup) 
    (makunbound 'a-backup)) 

後來我才意識到,由於有這麼多的東西,宏是回答:

(defmacro let-if-bound (var value &rest body) 
    "Bind variable VAR to VALUE only if VAR is already bound." 
    (declare (indent 2)) 
    `(if (boundp ',var) 
     (let ((,var ,value)) 
     ,@body) 
    (progn ,@body))) 

(let-if-bound a t 
    ;; do things 
) 

(*)A 「特殊形式」 是特殊標記,以便其 參數不評估所有原始功能。大多數特殊形式定義了控制 結構或執行變量綁定 - 功能不能 做的事情。

每個特殊形式都有其自己的規則,其參數評估爲 ,並且在沒有評估的情況下使用哪些參數。評估的特定參數是否爲 可能取決於評估其他參數的結果。

+0

@phills所有謝謝回答的第一個。我理解let構造的侷限性。我也認爲你身邊的工作提到了。我只是不喜歡耦合綁定和解除綁定相同的表達式。 – kindahero 2012-03-21 05:22:07

+0

編輯了該問題以修正括號。在接受之前我會再等一會兒。 – kindahero 2012-03-21 05:27:45

+0

最後我明白了......看到編輯答案。 – phils 2012-03-21 06:01:11

1

我認爲,「規範」的方式來做到這將是

(let ((bound (boundp 'a)) 
     (a t)) 
    (unless bound (makunbound 'a)) 
    ...blabla...) 
+0

感謝你的回答,Infact我結束了使用完全相同的過程, – kindahero 2012-03-21 15:12:59

+0

啊,這比我的版本好一點。它也帶來了相同的警告,即在任何情況下,該範圍內的*賦值*到'a'都不會在該範圍內退出,所以無論您使用這種方法還是宏,都取決於您對'a'的'不關心'級別'如果它以前沒有綁定。 – phils 2012-03-21 22:53:22