I'm trying to write a macro that will define a function exactly once where I don't really care what the name of the function is. My thought was to generate a symbol, use
defun with that, and then put a special property on the symbol. The next time the macro is called, it looks for a symbol with this property first and generates a new symbol if it can't find one.
Here's my code:
(require 'dash) (require 'cl-lib) (defun lispdoc-find-handler (key) (--find (and (functionp it) (-> (symbol-plist it) (plist-get 'lispdoc-section-handler) (eq key))) (append obarray nil))) (defmacro lispdoc-defsechandler (key &rest body) (let ((sym (or (lispdoc-find-handler key) ;; use existing symbol if defined (cl-gensym)))) `(progn (defun ,sym ,@body) (put ',sym 'lispdoc-section-handler ,key) (cons ,key ',sym)))) ;; test (lispdoc-defsechandler :test (examples) (prin1-to-string examples)) (when-let ((f (lispdoc-find-handler :test))) (funcall f '(1 2 3 4 5)))
eval-defun my call to
lispdoc-defsechandler, I get a different symbol every time (where I'm very clearly checking to see if it already exists first). When I
macroexpand-last-sexp it, I get the following:
(progn (defun G564 (meta examples) (prin1-to-string examples)) (put 'G564 'lispdoc-section-handler :test) (cons :test 'G564))
Evaluating this gives me the same ultimate return value (i.e.,
(:test . G564)), but now the macro always gives the same result, too (i.e., the function has actually been defined).
Even if I minimize the macro to just the following
(defmacro lispdoc-defsechandler (key &rest body) (let ((sym (or (lispdoc-find-handler key) (cl-gensym)))) `(defun ,sym ,@body)))
I still get the generated
sym as a return value, but its function-value isn't defined. What's going on here? If the function isn't being defined, how is it getting evaluated at all?