我想有条件地将不同的代码片段写入我的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
控件的字节编译结果(对于add-to-list
函数是调用)编写到已编译的.elc
文件中?在这种情况下,我希望(add-to-list 'auto-mode-alist '("\\.gitconfig\\'" . B-mode))
写入.elc
文件。
答案 0 :(得分:1)
我认为对此的答案是宏:如果你编写一个扩展为你想要的代码的宏,那么只需将宏调用放在顶层,那么宏的扩展将在编译时结束文件。
所以:
(defmacro foo ()
(if <compile-time-condition>
`(setq ...)
`(setq ...)))
(foo)
警告:您只能在编译时对您知道的事情进行条件化:您在UID上调度的示例可能无法达到预期效果。
答案 1 :(得分:1)
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
。