4

I read https://github.com/lunaryorn/blog/blob/master/posts/byte-compiling-eval-after-load.md which contains this code:

(defmacro stante-after (feature &rest forms)
  `(,(if (or (not byte-compile-current-file)
             (if (symbolp feature)
                 (require feature nil :no-error)
               (load feature :no-message :no-error)))
         'progn
       (message "stante-after: cannot find %s" feature)
       'with-no-warnings)
    (eval-after-load ',feature
      `(funcall (function ,(lambda () ,@forms))))))

I read (info "(elisp)") but can't find a strict statement that the inner macro is expanded before the outer one. I can't find the semantics of nested backquotes.

I understand that ,(lambda () ,@forms) has a comma before lambda in order to mark the form as functional and that triggers byte-compilation, but I can't figure out in which order that comma is interpreted by the backquote macro.

3
  • If unsure, use macroexpand. Without attempting to eval your code, I'd wait for a "comma outside backquote" error message, but that's because I'm used to Common Lisp, and it's a bit stricter in this regard. In other words, I don't think that forms will be replaced with the value of the argument, instead it will be undefined at the time the lambda is called. PS. What were you trying to achieve when you put a comma before lambda?
    – wvxvw
    Commented Apr 3, 2015 at 7:20
  • 1
    What were you trying to achieve when you put a comma before lambda it is special trick which discussed in pointed article - Emacs byte-compile anonymous lambdas in compilation mode, when it see (progn ...) form it leave code for interpretation.
    – gavenkoa
    Commented Apr 3, 2015 at 7:44
  • 1
    Ah, sorry, I didn't make a connection. Well, to me it seems like relying on a behavior that is a bug of a system, not an intended functionality. I wouldn't use such code. Wrt your other question: the order of macro expansion, that, unfortunately, can't be answered with certainty. Some macros expand the forms they are given and others don't. For example, macros inside cl-loop aren't expanded before they are used to build loop code, but it's not uncommon to use macroexpand during macro expansion. I don't know of ELisp-specific examples, but CL iterate library (unlike loop) expands them.
    – wvxvw
    Commented Apr 3, 2015 at 11:54

1 Answer 1

5

Comma and backquote are transformed by the reader into regular function calls with the following sexp as argument.

(read "`(list ,fill-column `(list ,fill-column))")
;; => (\` (list (\, fill-column) (\` (list (\, fill-column)))))

You can look-up the backquote macro's help. Comma is actually not a macro, but like a marker for backquote, i.e. it's argument gets evaluated. Also, backquote does not recurse into another nested backquote.

(eval (read "`(list ,fill-column `(list ,fill-column))"))
;; => (list 70 (\` (list (\, fill-column))))

So you can view backquote as a regular macro and apply your knowledge about them.

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.