I am having a problem working with closures. I hope I can explain this clearly. When I try to start a compilation I typically do it like this:
(let ((dir (get-dir))
(model-root root)
(default-directory dir)
(compilation-environment env)
(compilation-buffer-name-function
(lambda (mode)
(format "*%s %s %s*"
(f-filename model-root)
(downcase mode)
(f-filename dir)))))
(compilation-start "some command" 'foo-mode))
But, I want to use a custom function instead of compilation-start
. This custom function will add commands to a queue instead of running them right away. However that means I need to capture the dynamically scoped variables from the let
binding. This works fine except for when I get the value of compilation-buffer-name-function
, it evaluates to a closure like this.
(closure ((model-root . "/root/path/") (dir . "/some/directory/") t)
(mode) (format "%s %s %s" (f-filename model-root) (downcase mode) (f-filename dir)))
The problem is, that form is not a valid form for evaluation. It gives me the error let: Symbol’s function definition is void: closure
. I am aware the closure
is not a real function and that is merely an implementation detail that is exposed to the user.
Here is my code to call compilation-start
when the command is ready (this is the code that is giving the error).
(cl-loop for command in compilation-queued-commands
with bindings = (car command)
with args = (cdr command)
do (eval `(let ,bindings
(apply 'compilation-start ',(-flatten args)))))
This is the code I am using to capture the dynamic variables
(defvar compilation-dynamic-closures '(compilation-buffer-name-function
compilation-environment
default-directory))
(add-to-list 'compilation-queued-commands
(list (mapcar (lambda (var)
(list var (symbol-value var)))
compilation-dynamic-closures)
compilation-args))
So my question is, how can I capture and replay this closure later?