fset
fset copied to clipboard
`@` only with function argument
I'm using @ as funcall, and this doesn't work well with functions not taking any arguments.
; in: DEFUN LEARNER
; (FSET:@ (MANG::MATCH-EVERYTHING-GENERATOR))
; --> NEW-LET:LET LET IF
; ==>
; (FSET:LOOKUP #:FN-0)
;
; caught STYLE-WARNING:
; The function was called with one argument, but wants exactly two.
I think reimplementing @ like this should fix the problem, since lookup takes 2 arguments either way:
(defmacro @ (fn-or-collection &rest args)
"A little hack with two purposes: (1) to make it easy to make FSet maps
behave like Lisp functions in certain contexts; and (2) to somewhat lessen the
pain of writing higher-order code in a two-namespace Lisp like Common Lisp.
The idea is that you can write `(@ fn arg)', and if `fn' is a Lisp function,
it will be funcalled on the argument; otherwise `lookup' (q.v.) will be called
on `fn' and `arg'. To allow for `@' to be used in more contexts, it actually
can take any number of `args', though `lookup' always takes exactly two. Thus
you can write `(@ fn arg1 arg2 ...)' when you just want a shorter name for
`funcall'. As a matter of style, it is suggested that `@' be used only for
side-effect-free functions. Also, though this doc string has spoken only of
FSet maps, `@' can be used with any type that `lookup' works on. Can be used
with `setf', but only on collections, not functions, of course."
(if (or (not args)
(> (length args) 1))
;; Hmm. We _could_ listify `args' and use that as the map key.
`(funcall ,fn-or-collection . ,args)
(let ((fn-var (gensym "FN-")))
`(let ((,fn-var ,fn-or-collection))
(if (functionp ,fn-var)
(funcall ,fn-var . ,args)
;; We do it this way rather than just `(lookup fn-or-collection (car args))'
;; so that we get the right error when `args' is not of length 1. If this
;; doesn't get compiled well everyplace we care about, we could test the
;; length and issue the error ourselves (if that helps).
(lookup ,fn-var . ,args))))))