fset icon indicating copy to clipboard operation
fset copied to clipboard

`@` only with function argument

Open Aksej opened this issue 8 years ago • 0 comments

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))))))

Aksej avatar Oct 08 '17 08:10 Aksej