Search code examples
emacslispelisp

Writing different pieces of code to the compiled (.elc) file, based on different conditions


I want to conditionally write different pieces of codes to the compiled version of my elisp files (.elc), I can do this with function definitions:

(defalias 'my-test
  (eval-when-compile
    (if nil 
      (lambda ()
        (message "True"))
      (lambda ()
        (message "False")))))

With the code above, I can assign different anonymous functions to my-test based on different conditions and the result will get written to the compiled .elc file. But what I want to write is function calls in file scope. like so:

(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)))

The code gets evaluated in compile time and the results of evaluation will only be available in the compilation process and after that nothing goes to .elc, because I didn't assign it to anything, but how can I actually write the byte-compiled results of if control (which is a call to add-to-list function) to the compiled .elc file? in this case I wanted (add-to-list 'auto-mode-alist '("\\.gitconfig\\'" . B-mode)) to get written to the .elc file.


Solution

  • I think the answer to this is macros: if you write a macro which expands to the code you want, then simply place an invocation of the macro at top-level, then the expansion of the macro will end up in the compiled file.

    So:

    (defmacro foo ()
      (if <compile-time-condition>
          `(setq ...)
          `(setq ...)))
    
    (foo)
    

    Caveat: you can only conditionalise on things you know at compile time: your example of dispatching on UID might not do what you expect.