Funcallable Macros
Thursday, May 27, 2004
Ever want to funcall or map using a macro? Although there are some good reasons for not doing this (see this thread for some of them), Lars Brinkhoff posted some code (actually 2 different versions) that shows how one could. Cute.
;;; Lisp apprentice's wet dream: funcallable macros.;;; Probable newbie usage example: (funcallable-macro 'and) ;;; (reduce #`and '(t t t nil t t)) ;;; Two implementations are provided: one trivial using eval, and one ;;; that memoizes compiled functions.
;;; #1 Trivial version using eval. (defun funcallable-macro (name) (lambda (&rest args) (eval (cons name args))))
;;; #2 Version that memoizes compiled functions. (defun funcallable-macro (name) (let ((table (make-hash-table :test #'eql))) (lambda (&rest args) (let ((n (length args))) (apply (or (gethash n table) (setf (gethash n table) (make-funcallable-macro-function name n))) args)))))
(defun make-funcallable-macro-function (name n) (let ((args nil)) (dotimes (i n) (push (gensym) args)) (compile nil `(lambda ,args (,name ,@args)))))
;;; Do this for either version that is used. (set-dispatch-macro-character ## #` (lambda (s c n) `(funcallable-macro ',(read s t nil t))))

