Am Mo., 16. März 2020 um 23:18 Uhr schrieb Lassi Kortela <xxxxxx@lassi.io>:
> Let's try to keep at least this discussion at a technical level.

Sorry if I went overboard. Simplicity is one of the main technical
concerns in my book so it's difficult to stay neutral at times.

It is hard to agree on what "simplicity" means so it is hard to argue on the basis of "simplicity".

In some sense, `define-macro' is "simpler" than `syntax-rules'. BASIC is "simpler" than Scheme. Higher-order procedures are complicated. Promises are complicated. Linear-update procedures are complicated.


> At least from that point of view, the CL model doesn't seem to provide
> anything but syntactic sugar over an extra plist argument.

You are right:

(defun foo (&key a b c) (list a b c))

(apply #'foo '(:a 1 :c 3)) ; => (1 NIL 3)

Note that 177 has subtly different `apply` semantics than CL (more below).

> If the procedure `foo' is known at the call site, a good compiler can
> optimize a lot.  Even plist arguments encoding keywords can be handled
> in an optimized way.

Yeah, that's the scenario I was wondering about. Calls to unknown
procedures will have to use the slow path. But isn't that the case also
for Kawa/Racket-style kwargs? It may be able to omit some checks, but it
will still have to internally make a hash-table or list out of the
kwargs. I guess the callee can assume the keyword list is sorted/hashed
properly and doesn't need to type-check the keywords or the collection
containing them and their values.

> In general, `foo' is not known at the call site or `foo' is defined in
> some other module, for which no compile-time information is available.

Is it the usual case that the information isn't preserved across module
boundaries? I had assumed that at least the fastest compilers like
Gambit and Chez would preserve it.

See my previous answer to Shiro why, in general, such information cannot be preserved. In specific cases, it can and good compilers will do that.
 

> With the CL model, `foo' has to be treated as an ordinary procedure
> taking 4 arguments.  Otherwise, as I have described in my first post in
> this thread, section 4.1.3 of the R7RS-small would be violated.

That's correct as far as I can tell.

Since SRFI 177 works with both CL style and Kawa/Racket style, it cannot
guarantee that keyword arguments may be passed using ordinary `apply`.
The lack of this guarantee is a difference from CL.

However, 177 can guarantee that `apply` works when no kwargs (and no
arguments in rest position) are given. Though it cannot help with any
compile-time checks.

In some sense, SRFI 177 (with the original syntax) follows Kawa's approach but uses the CL-semantics in its implementation.