Python 3 has the function locals()
ans globals()
that allow passing the named values of the current scope at least for read-only purposes to a function.
In emacs lisp I want to write a function for string interpolation. It would need access to the lexical variables of the calling scope for this purpose. Since I want to avoid recompilation of other files when the macro changes, the obvious solution – using a macro – is not viable.
Is there some possibility to do this in emacs lisp?
I already tried the function lisp--local-variables
but it doesn't work with lexical-binding
being t
.
(Internally, the lexical environment is an alist of symbol-value pairs, with the final element in the alist being the symbol `t' rather than a cons cell. Such an alist can be passed as the second argument to the `eval' function, in order to specify a lexical environment in which to evaluate a form. *Note Eval::. Most Emacs Lisp programs, however, should not interact directly with lexical environments in this way; only specialized programs like debuggers.)
Currently, an Emacs Lisp closure object is represented by a list with the symbol `closure' as the first element, a list representing the lexical environment as the second element, and the argument list and body forms as the remaining elements:
;; lexical binding is enabled. (lambda (x) (* x x)) => (closure (t) (x) (* x x))
However, the fact that the internal structure of a closure is "exposed" to the rest of the Lisp world is considered an internal implementation detail. For this reason, we recommend against directly examining or altering the structure of closure objects.
If I were to do this, I would not make a string interpolation function, I would make a string interpolation macro, that returns a suitable snippet of code to compute the interpolated string in the correct lexical environment.
That is, after all, one of the really handy uses for macros.
If you write and debug the macro in "isolation" (before you heavily utilize it in other code), your fear of needing to recompile should be mostly just that, a fear. Once debugged, you shouldn't need to change the macro for existing functionality and if you need to add new functionality, it's not anything taht's already been used (however, it's probably not a bad idea to recompile code once in a while, anyway).