【问题标题】:Elisp: boundp in letElisp:在 let 中的 boundp
【发布时间】:2012-04-05 14:25:57
【问题描述】:

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

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

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

【问题讨论】:

    标签: emacs elisp let


    【解决方案1】:

    代码失败并显示:(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
      )
    

    (*) “特殊形式”是一个特别标记的原始函数,因此它的 并非所有参数都被评估。大多数特殊形式定义控制 结构或执行变量绑定——函数不能的东西 做。

    每种特殊形式都有自己的参数评估规则 并且无需评估即可使用。一个特定的论点是否 评估可能取决于评估其他参数的结果。

    【讨论】:

    • @phills 首先感谢您的回答。我理解 let 构造的局限性。我还认为你提到的工作。我只是不喜欢耦合绑定和解除绑定相同的表达式。
    • 编辑了问题以修正括号。我会再等一段时间再接受。
    • @phils 如果编译代码,定义的宏解决方案将不是动态的。你应该修复它。
    • event_jr:谢谢;我很乐意修复它,但恐怕我不确定这个问题(并且在测试时无法引起任何问题)。您能否详细说明一下代码不起作用的情况?
    • @phils (if (boundp var 是宏的一部分,而不是宏发出的形式。这意味着宏发出的表单将取决于编译时 var 的值,而不是运行时。
    【解决方案2】:

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

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

    【讨论】:

    • 感谢您的回答。事实上,我最终使用的是完全相同的。
    • 啊,这比我的版本好一点。它带有同样的警告,即在该范围内对aassignments 在任何一种情况下都不会在该范围的退出中存活,因此您是使用这种方法还是宏取决于您的“不”级别关心'a,如果以前没有绑定的话。
    猜你喜欢
    • 2021-12-26
    • 2013-09-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-11-27
    • 2010-10-07
    • 2015-10-18
    • 2015-11-17
    相关资源
    最近更新 更多