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

时间:2016-06-30 02:35:44

标签: emacs bytecode

在字节编译时,如何用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 "\302 !)\207" [my-auto generated-autoload-file prin1] 2])

但是,我可以改为

(defalias 'test #[nil "\301\302!)\207" [generated-autoload-file "somefile.el" prin1] 2])

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

1 个答案:

答案 0 :(得分:1)

如果只想在函数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 "\300\301!\207"
    ["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)))

结果应该符合预期。