The byte-compiler does not currently seem to recognise that a function has been defined when using defun within a let expression under lexical-binding, as explained in Stefan's answer to this question.

In my own initialisation file, I have found that I can make the defun-within-let obvious to the byte-compiler by wrapping the whole form in eval-and-compile, as I noted under the same question.

My multipart question is:

  1. What further effects (desirable or otherwise) does placing the defun-within-let within eval-and-compile have compared to the bare version w.r.t. interpretation/byte-compilation/macroexpansion, etc.
  2. I roughly understand by looking at the definition of defun that it is a glorified wrapper around defalias. Apart from forgoing the explicit (lambda () ...) (or other function value) which needs to be passed to defalias, is there some other subtle difference between defalias and defun, e.g. different treatment by the byte-compiler?
  • A defun inside a let is not a toplevel defun.
    – Drew
    Commented May 7, 2017 at 2:24
  • @Drew I think I'm missing the correct meaning of a toplevel defun - could you please explain or point me to some documentation?
    – Basil
    Commented May 7, 2017 at 2:27
  • 1
    (emacs)Defuns and its descendant nodes come closest. Use C-s top-level in the manual to see more. A top-level sexp is just a sexp that is not enclosed in another sexp within a file or buffer (or perhaps some other scope of discourse).
    – Drew
    Commented May 7, 2017 at 2:31
  • @Drew Thanks for clarifying; I'll modify the question accordingly. One thing that searching through the manual did not clarify is whether the descendents of certain special forms (particularly progn) might still be considered "top-level" in some capacity, e.g. in the context of byte-compiler declarations, macro calls, etc.
    – Basil
    Commented May 7, 2017 at 2:47
  • 1
    If some such context treats a definition or other sexp specially, as if it were "top level", then that's not documented, as far as I know. Which generally means you should not depend on it, i.e., today's behavior might well not be respected tomorrow.
    – Drew
    Commented May 7, 2017 at 4:34

1 Answer 1


One bad side effect I discovered is when function's body itself also has eval-and-compile form (in addition to the outer one). In particular, compared to the case when there is only eval-and-compile in function's body (and no outer one), after byte compiling a file with a target function and loading the byte compiled file, the call to the loaded function does not seem to yield evaluation of the function's body enclosed by eval-and-compile.

To be honest, I believe this is a bug like some others. For example, nested eval-and-compile forms (without defun in the middle like in the case above) cause the innermost body to be evaluated twice but only at compile time, while eval-when-compile nested into eval-and-compile does not (surprise!) exhibit this issue.

The conclusion I arrived at, was to minimize the of use eval-and-compile and use it with care anyways to always be sure that nesting will/should not happen.


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.