2012-03-21 41 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