reddit / emacs

Macro expansion inside let scope?

quokka70 · 2022-10-05 15:27
The transient package has a macro `transient-define-prefix` ([docs](https://www.gnu.org/software/emacs/manual/html_mono/transient.html#Defining-Transients)). The following defines a complete prefix: (setq l1 '(("vl" "visual lines" visual-line-mode))) (transient-define-prefix foo1 () "docstring" [:pad-keys t ["Appearance" l1]]) (The macro allows for a list of "elements" like `l1` to be interpolated, something like a `,@` splice in a backtick context.) But having the variable `l1` lying around feels like a loose end. The following approach looks better: (let ((l2 '(("vl" "visual lines" visual-line-mode)))) (transient-define-prefix foo2 () "docstring" [:pad-keys t ["Appearance" l2]])) But it fails with "Symbol’s value as variable is void: l2" My understanding of elisp scope is clearly lacking. Is the problem that the `transient-define-prefix` macro is expanded within the `let` scope but the result is not evaluated until after the `let` scope is discarded? The elisp documentation for macros says that "[t]he Lisp interpreter proceeds to evaluate the expansion as soon as it comes back from the macro" but I may be misunderstanding this.
nv-elisp · 2022-10-05 17:09
If you look at the definition of `transient-define-suffix`, it calls `transient--parse-child` which uses `symbol-value` on the `l2` symbol in this case. `symbol-value` only considers the global value of a symbol.
quokka70 · 2022-10-05 17:45
Thanks! I spent some time looking through the definition but my elisp is weak and my eyes glazed over. Edit: Oh, and it depends on whether or not lexical binding is enabled.
7890yuiop · 2022-10-06 01:19
Note that `symbol-value` doesn't care whether or not lexical binding is enabled, because lexical variables are not actually associated with the symbol of the same name.