Am Do., 5. März 2020 um 20:58 Uhr schrieb John Cowan <xxxxxx@ccil.org>:


On Tue, Mar 3, 2020 at 2:43 AM Marc Nieper-Wißkirchen <xxxxxx@nieper-wisskirchen.de> wrote:
> This problem can be avoided with the (call/kw a b c (d 4 e 5 f 6))
> syntax but other people didn't like it :)
This syntax is better than having to rely on a hack. As long SRFI 177 is compatible with native systems, people can still use native syntaxes if they like them better or add the hack with the ":" parsing themselves. For that, it doesn't have to be part of the language standard.
What people objected to was the parentheses, which were only necessary to make a syntax-rules implementation possible.  Now that we have abandoned that goal in favor of define-macro, syntax-case, and explicit renaming implementations (which covers essentially all Schemes), a syntax like

(call/kw a b c &kw d 4 e 5 f 6)

That looks very good to me! I hope the R6RS camp won't complain because "&" is already used there to introduce condition types.

Such a macro is even implementable with syntax-rules, isn't it?

One could even drop the "/kw" so that we do not double "kw":

(call a b c &kw d 4 e 5 f 6)

Or, if we want to be notationally disjoint to the R6RS condition types:

(call a b c /kw d 4 e 5 f 6).

The call macro would expand into an ordinary procedure call if there is no /kw present:

(call a b c) => (a b c)


is perfectly feasible and I think desirable.  No problems with colon identifiers or with #: lexical syntax extensions.  Then the only special case is &kw (or whatever other identifier seems desirable), which becomes in effect a syntactic keyword of this macro, like else and => in cond.

Perhaps of interest: Chicken has recently changed so that keywords are not symbols (they are disjoint at run time) and not identifiers either: they cannot be rebound.

I really would like to see an R7RS reader flag that allows an R7RS-compatible implementation to read SRFI 88 keywords (in my opinion still the best syntax) as keywords and not as symbols/identifiers.
 
 

This works for case-lambda because the different paths are only distinguished by the number of arguments and there is a small subset of often used numbers of arguments. For keyword arguments, this does not work as there is no small subset of "usually" used keyword arguments.

There might be, and indeed compilers could collect information about which keywords are used relatively easily and cache it for use or modification by other compilation runs.  This is like doing permissive type inference and saving the evidence.  But that's by the way.

With whole program optimization you can, of course, do all the magic. With separately compiled or shared (system) libraries, this may not be possible. In any case, it would be by a magnitude more complicated than a simple case-lambda implementation in which a procedure whose call sites are not known to have 5 entry slots. The caller jumps to the right slot depending on the number of arguments received.

 
 
> There should be a way to write wrappers for "procedures" taking keyword
> arguments. In particular, there has to be a way to pass keyword
> arguments down to callees.

As I noted earlier, this feature (CL &allow-other-keys lambda keyword and :allow-other-keys runtime keyword) is interesting and occasionally useful, but I would not call it necessary.

The main argument against "procedures" with keyword arguments being macros instead of actual procedures was that procedures with keyword arguments shall be first-class citizens as other procedures. However, this is not very helpful if the keyword list itself cannot be reified as a first-class citizen. (This seems comparable to the situation with ordinary procedures when we have no "apply" and no rest arguments.)

Marc