Hey all,
When I started looking at incorporating Miles's
`lambda-with-constant-bindings', I realised there were a number of
places in the code where we've done things like:
`(lambda (...)
...
(switch-to-buffer ,(current-buffer)))
i.e. we're grabbing the values of arbitrary forms from the defining
environment, not just variables. So, I've reworked Miles's macro a
little and have come up with something equally hairy that seems to do
the job:
(defvar tla--gensym-counter 0)
(defun tla--gensym (&optional arg)
"Generate a new uninterned symbol.
The name is made by appending a number to PREFIX, default \"tla\"."
(let ((prefix (if (stringp arg) arg "tla"))
(num (if (integerp arg) arg
(prog1
tla--gensym-counter
(setq tla--gensym-counter (1+ tla--gensym-counter))))))
(make-symbol (format "%s%d" prefix num))))
(defun tla--capturing-lambda-helper (l)
(cond ((atom l) l)
((eq (car l) 'capture)
(let ((g (tla--gensym)))
(push (list g (cadr l)) captured-values)
g))
(t (mapcar 'tla--capturing-lambda-helper l))))
(defmacro tla--capturing-lambda (args &rest body)
"A `lambda' capable of capturing values from its defining environment.
Values to be captured should be surrounded by (capture ...).
For example:
(let* ((y 'lexical-y)
(l (tla--capturing-lambda ()
(list x (capture y)))))
(let ((y 'dynamic-y)
(x 'dynamic-x))
(funcall l)))
=> (dynamic-x lexical-y)
"
(let ((captured-values '()))
(let ((body (tla--capturing-lambda-helper body)))
``(lambda ,',args
(let (,,@(mapcar (lambda (var) ``(,',(car var)
',,(cadr var)))
captured-values))
(funcall ,(lambda () ,@body)))))))
So, the above would be written:
(capturing-lambda (...)
...
(switch-to-buffer (capture (current-buffer))))
I've tried this under Emacs and XEmacs and both seem to work correctly.
Does anyone have any thoughts on this? Is this something that would
count as a bugfix against 0.9, or should I introduce this in a
development branch?
Cheers,
Mark
--
Mark Triggs
<[EMAIL PROTECTED]>