Intricate lambda list syntax
Lassi Kortela 18 Oct 2019 08:26 UTC
> I checked with CLISP and #lisp, and they agree:
> optional arguments are filled before any keyword detection begins.
That's right.
(defun foo (&optional x &key y) (list x y))
(foo :y) ; => (:Y NIL)
(foo :y :y 1) ; => (:Y 1)
When you think through the ramifications, it's the logical choice when
keywords are self-evaluating objects, but it probably confuses everyone
at first.
Even more confusing is that keyword args can co-exist with a rest arg.
They receive the same portion of the arglist, the rest arg gets the raw
version and the keyword args the parsed one:
(defun foo (&optional x &rest r &key y) (list* x y r))
(foo) => (NIL NIL)
(foo :y) => (:Y NIL)
(foo :y :y 1) => (:Y 1 :Y 1)
Finally there's &allow-other-keys, default values and supplied-p
parameters. I left all of this out of 177 on purpose, as I think it
confuses users without offering much benefit.
Another fun fact: Racket has required keyword arguments. In fact they
are required by default unless you give them a default value.