在字节编译期间用符号值替换 let 绑定变量

Replace let bound variables with symbol value during byte-compile

如何在字节编译时用 emacs 中的值替换 let-bound 变量?例如,假设我有一些变量 my-auto,我可以用它在函数中的值替换它的符号名称吗?

(defvar my-auto "somefile.el")

(defun test ()
  (let ((generated-autoload-file my-auto))
    (prin1 generated-autoload-file)))

字节编译后我得到(有些符号不会显示,但你明白了)

(defalias 'test #[nil "2 !)7" [my-auto generated-autoload-file prin1] 2])

但是,我可以代替

(defalias 'test #[nil "12!)7" [generated-autoload-file "somefile.el" prin1] 2])

其中 my-auto 已替换为 "somefile.el"?我想我可以写一些宏,但我不确定如何重构一堆函数。

如果您只想在函数中使用它的值,为什么要定义全局动态变量 test?请考虑提出您真正的问题:您真正想做什么。

无论如何,这显然是您(自认为)想要的:

;;; foo.el --- tools -*- lexical-binding:t -*-

(eval-and-compile
  (let ((var  "somefile.el"))

    (defvar my-auto var)

    (defun test ()
      (let ((generated-autoload-file var))
        (prin1 generated-autoload-file)))))

确保将其放入 文件,第一行包含 lexical-binding 声明。字节编译文件。加载字节编译文件。然后检查(symbol-function 'test)。你会看到这样的东西:

#[0 "01!7"
    ["somefile.el" prin1]
    3 "\n\n(fn)"]


由 OP 添加,jenesaisquoi。这显然是他最终所做的:

另一种方法是创建一个在字节编译时扩展的宏,比如

(defmacro expand-thing (place)
  (or (and (symbolp place) (symbol-value place))
      ;; or do other checks
      (eval place)))

然后,字节编译后(先要宏!)

(defun test ()
  (let ((generated-autoload-file (expand-thing my-auto)))
    (prin1 generated-autoload-file)))

结果应该符合预期。