根据不同的条件,将不同的代码片段写入编译后的 (.elc) 文件
Writing different pieces of code to the compiled (.elc) file, based on different conditions
我想有条件地将不同的代码片段写入我的 elisp 文件 (.elc) 的编译版本,我可以使用函数定义来做到这一点:
(defalias 'my-test
(eval-when-compile
(if nil
(lambda ()
(message "True"))
(lambda ()
(message "False")))))
通过上面的代码,我可以根据不同的条件为my-test
分配不同的匿名函数,结果将写入编译后的.elc
文件。但是我想写的是函数调用在文件范围。像这样:
(eval-when-compile
(if nil
(add-to-list 'auto-mode-alist '("\.gitconfig\'" . A-mode))
(add-to-list 'auto-mode-alist '("\.gitconfig\'" . B-mode))))
;; or using `when' to either write a call or do nothing:
(eval-when-compile
(when (not (eq (user-uid) 0)) ; if uid != 0
(dangerous-call)))
代码在编译时被求值,求值结果只会在编译过程中可用,之后什么都不会进入.elc
,因为我没有将它赋值给任何东西,但是怎么能我实际上将 if
控件的 byte-compiled 结果(这是一个 call 到 add-to-list
函数)写到编译 .elc
文件?在这种情况下,我希望 (add-to-list 'auto-mode-alist '("\.gitconfig\'" . B-mode))
写入 .elc
文件。
我认为这个问题的答案是宏:如果你编写一个扩展为你想要的代码的宏,那么只需将宏的调用放在顶层,那么宏的扩展将结束于编译后的文件。
所以:
(defmacro foo ()
(if <compile-time-condition>
`(setq ...)
`(setq ...)))
(foo)
警告:您只能根据您在编译时知道的事情进行条件化:您在 UID 上调度的示例可能无法达到您的预期。
tfb 的答案通常是更好的选择,但对于一次性情况,您可能更愿意这样做
(if (eval-when-compile (my-test))
(add-to-list 'auto-mode-alist '("\.gitconfig\'" . A-mode))
(add-to-list 'auto-mode-alist '("\.gitconfig\'" . B-mode)))
甚至可以重写为
(add-to-list 'auto-mode-alist
`("\.gitconfig\'"
. ,(if (eval-when-compile (my-test)) 'A-mode 'B-mode)))
这依赖于编译器优化根据常数将(if <constant> a b)
变成a
或b
。
我想有条件地将不同的代码片段写入我的 elisp 文件 (.elc) 的编译版本,我可以使用函数定义来做到这一点:
(defalias 'my-test
(eval-when-compile
(if nil
(lambda ()
(message "True"))
(lambda ()
(message "False")))))
通过上面的代码,我可以根据不同的条件为my-test
分配不同的匿名函数,结果将写入编译后的.elc
文件。但是我想写的是函数调用在文件范围。像这样:
(eval-when-compile
(if nil
(add-to-list 'auto-mode-alist '("\.gitconfig\'" . A-mode))
(add-to-list 'auto-mode-alist '("\.gitconfig\'" . B-mode))))
;; or using `when' to either write a call or do nothing:
(eval-when-compile
(when (not (eq (user-uid) 0)) ; if uid != 0
(dangerous-call)))
代码在编译时被求值,求值结果只会在编译过程中可用,之后什么都不会进入.elc
,因为我没有将它赋值给任何东西,但是怎么能我实际上将 if
控件的 byte-compiled 结果(这是一个 call 到 add-to-list
函数)写到编译 .elc
文件?在这种情况下,我希望 (add-to-list 'auto-mode-alist '("\.gitconfig\'" . B-mode))
写入 .elc
文件。
我认为这个问题的答案是宏:如果你编写一个扩展为你想要的代码的宏,那么只需将宏的调用放在顶层,那么宏的扩展将结束于编译后的文件。
所以:
(defmacro foo ()
(if <compile-time-condition>
`(setq ...)
`(setq ...)))
(foo)
警告:您只能根据您在编译时知道的事情进行条件化:您在 UID 上调度的示例可能无法达到您的预期。
tfb 的答案通常是更好的选择,但对于一次性情况,您可能更愿意这样做
(if (eval-when-compile (my-test))
(add-to-list 'auto-mode-alist '("\.gitconfig\'" . A-mode))
(add-to-list 'auto-mode-alist '("\.gitconfig\'" . B-mode)))
甚至可以重写为
(add-to-list 'auto-mode-alist
`("\.gitconfig\'"
. ,(if (eval-when-compile (my-test)) 'A-mode 'B-mode)))
这依赖于编译器优化根据常数将(if <constant> a b)
变成a
或b
。