3

如何检查变量是否在 let 构造中定义?

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

我要做的是检查a之前是否有界,如果已经有,请将其绑定到t本地。否则根本不在乎a

4

2 回答 2

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
  )

(*) “特殊形式”是一个特别标记的原始函数,因此它的参数不会全部被评估。大多数特殊形式定义控制结构或执行变量绑定——函数不能做的事情。

每种特殊形式都有自己的规则,对哪些参数进行评估,哪些在不评估的情况下使用。是否评估特定参数可能取决于评估其他参数的结果。

于 2012-03-21T04:30:57.770 回答
1

我认为这样做的“规范”方式是

(let ((bound (boundp 'a))
      (a t))
  (unless bound (makunbound 'a))
  ...blabla...)
于 2012-03-21T12:56:34.487 回答