Procedures with keyword arguments should be macros not procedures Marc Nieper-Wißkirchen (17 Oct 2019 09:17 UTC)
Re: Procedures with keyword arguments should be macros not procedures Marc Nieper-Wißkirchen (17 Oct 2019 10:48 UTC)
Re: Procedures with keyword arguments should be macros not procedures Lassi Kortela (17 Oct 2019 21:31 UTC)
Intricate lambda list syntax Lassi Kortela (18 Oct 2019 08:26 UTC)
Re: Intricate lambda list syntax Shiro Kawai (18 Oct 2019 09:18 UTC)
Re: Intricate lambda list syntax Lassi Kortela (18 Oct 2019 14:29 UTC)
Re: Intricate lambda list syntax Shiro Kawai (18 Oct 2019 17:32 UTC)

Re: Procedures with keyword arguments should be macros not procedures Lassi Kortela 17 Oct 2019 21:31 UTC

Thanks for chiming in Per! The Kawa implementation of 177 was especially
easy.

> Consider:
>      (f x y z)
> Obvious a call to f with 3 positional (non-keyword) arguments, right?
>
> But what about:
>      (define y k1:)
>      (f x y z)
>
> Ooops. Turns out if was 1 positional and 1 keyword argument.
> But only if f allows keyword arguments.
>
> Unless you have some kind of type-checking/data-flow you can't guard
> against this.  Even with that type of analysis you can't always *prove*
> whether y is a keyword or not, so you have to compile conservative code
> and check at run-time.

Is the following a reasonable summary?

Common Lisp style:

* Find out the arity of `f`

* If `y` appears in the argument list before the position where
   keywords start, treat it as an optional arg (not a keyword arg) no
   matter what kind of object it is (keyword, list, anything else).

* Otherwise, if `f` takes keyword args and `y` is an even distance
   at/after the keyword start position then assert that `y` is a
   keyword object, thet `f` takes that particular keyword, that there
   is an object following `y`, and assign that object to the keyword
   pointed to by `y`.

Kawa/Racket style:

* Arity of `f` does not need to be known at call site, because
   keywords can always be passed in a separate part of the stack frame
   apart from positional and rest arguments.

* Never need to check whether `y` is a keyword object.

* Even if the static analyzer does not know which keyword args `foo`
   accepts, it can sort the keywords given by the caller at the call
   site, so they get pushed into the stack frame in the right order.

* There is never confusion about whether a particular arguments
   belongs to the optional/rest arguments or the keyword arguments.

So with the latter style, the compiler can implement more
optimizations in more situations with simpler code. And the user can
be confident that keywords in a procedure call are always keyword
arguments unless the keyword is quoted.

The former style is more flexible and syntactically simpler, but its
runtime behavior is more complex. Consequently the compiler has to
work harder, or leave more checking to be done at run time.