【问题标题】:How do I avoid eager macro expansion failures in emacs macros?如何避免 emacs 宏中急切的宏扩展失败?
【发布时间】:2016-05-07 03:49:22
【问题描述】:

我定义了这个宏:

(defmacro with-current-directory (directory &rest body)
  "Set the working directory temporarily set to DIRECTORY and run BODY.
DIRECTORY is expanded"
  `(let ((default-directory
          ,(file-name-as-directory
            (expand-file-name (eval directory)))))
     ,@body))

我在一些在 emacs 打开时加载的 lisp 函数中使用它。我总是收到这些警告:

Eager macro-expansion failure: (void-variable repo-dir)
Eager macro-expansion failure: (wrong-type-argument stringp nil)

我理解这是因为这些变量在加载时没有定义,并且 emacs 正在尝试评估它们。我的问题是,如何避免收到这些警告。有没有办法定义宏,这样就不会发生?我不知道如何使用变量的值,而不是变量本身的符号。

【问题讨论】:

    标签: emacs macros


    【解决方案1】:

    像这样:

    `(let ((default-directory
            (file-name-as-directory (expand-file-name ,directory))))
    

    由于directory 不是值,而是将计算为该值的 lisp 表达式,因此您需要将表达式插入(使用逗号运算符)到宏的扩展中。如果您在调用file-name-as-directory 之前放置逗号,则您必须能够在宏扩展时根据表达式的标记 计算目录,如果directory 指的是一个变量名。

    【讨论】:

    • 谢谢。我试过了,但我看到(let ((v "~/")) (macroexpand '(with-current-directory v (shell-command "ls")))) 给了我:(let ((default-directory (file-name-as-directory ...))) (shell-command "ls")),我认为它不起作用,因为......我应该尝试一下,因为它确实有效!
    【解决方案2】:

    看起来有人打败了我。看另一个答案。

    您不应该在扩展时评估文件名扩展。此外,不应存在 eval 调用。在宏扩展期间唯一应该发生的事情是将目录的值放在返回的表达式中。删除 eval 并将逗号放在目录前面。

    很高兴知道,无论何时您使用 eval,您都可能做错了什么

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2023-03-07
      • 2010-12-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-11-21
      相关资源
      最近更新 更多