intro
Sometimes I want to generate a function programmatically as opposed to defining
one with defun
. You may wondering why I'd want to do this. Well, it's
complicated but just bear with me for a moment.
(defun void-defun (fn)
(let ((name (gensym "void-defun-")))
(eval
`(progn
(message "Created function: %S" name)
(defun ,name ()
(funcall #',fn))))
name))
problem
When I test whether the function is bound with the following code, all is well.
(let ((fn (void-defun (lambda () 2))))
(and (fboundp fn) (= 2 (funcall fn)) fn))
;; => void-defun-69
after the test
However, after evaluating this test code and calling the function (whose name I
know from the *messages*
buffer) I get a void-function error. I expected the
function to be bound as indicated by my test. It is as if the function was bound
temporarily for the execution of my test form then unbound again.
;; This 69 is just as an example of a name I could get.
(funcall #'void-defun-69)
;; => eval: Symbol’s function definition is void: void-defun-69
question
Why does this happen? And how can I avoid this?
eval
?defun!
which is the same asdefun
except that after the docstring it is possible to supply keyword arguments such as(defun! fn () (:expire t) (:after message) (message "Just messaged"))
. This would result in a function that is an after advice tomessage
and would unbind itself after its first call. I have wanted to call this macro via a function e.g. (void-defun (lambda () (message "hi") :expire t :after #'hi). I've heard it is not good practice to use eval. Before this I had(funcall (backquote (lambda () ...))
to avoideval