Am Di., 3. März 2020 um 13:27 Uhr schrieb Lassi Kortela <xxxxxx@lassi.io>:
> Aside from the macro expansion issue, users may really ask about a way
> to choose identifiers that do no necessarily have the same name as the
> keyword symbols.
>
> For example, consider some procedure that constructs its result using
> CONS. You may later want to add some optional keyword argument called
> `cons', so that the user can explicitly specify the constructor used,
> e.g. `ipair' from SRFI 116.
>
> In the body of that procedure, you don't want to shadow the cons binding.
>
> Example:
>
> (define CONS cons) ; ?!
>
> (define/kw (map proc lst (cons))
>    (let ((cons (or cons CONS)))
>      (fold-right (lambda (x res) (cons (proc x) res)) '() lst)))
>
> The line marked with "?!" shouldn't be made necessary.

That's true. Traditionally Schemers have used names like `kons`, which I
agree is ugly. In keyword args it would be even uglier since the name
`kons` would become part of the procedure's public interface, instead of
being hidden in the internals only.

For 177, I would go with the simplicity of:

(define map
   (let ((standard-cons cons))
     (lambda/kw (proc lst cons)
       (let ((cons (or cons standard-cons)))
         (fold-right ...)))))

I think it looks clearer than:

(define/kw (map proc lst ((user-cons cons))
   (let ((user-cons (or user-cons cons)))
     (fold-right ...)))

Your version needs a sufficiently intelligent compiler to provide the same performance. Furthermore, what would you do if a keyword argument is not named after a procedure but after a syntactic keyword. Do you want to wrap everything inside `let-syntax'??? (For example, it is reasonable to use "cond" as a name for a keyword.)


> What do you mean by "If we can find a simple way to add it to ..."? Is
> there a hard way?

I mean that adding an optional sublist at the end of the keyword list
makes the full syntax of lambda/kw and define/kw more complex for people
reading in the manual about how to use it.

If you care about these people, it is easy to make two entries. One that describes the base version, and one that describes the general one.
 

There should probably be 2 or 3 variants of lambda/kw, each with
increasing complexity. The simplest one would be like the one now in
177, the more complex ones would have all available features. Ideally
the complex ones' syntax is a compatible superset of the simpler ones.

> BTW, the above is another example where keyword arguments makes a lot
> sense together with rest arguments:
>
> (map proc lst1 lst2 lst3 lst4 cons: ipair)
>
> looks perfectly sane. (The syntax is not set in stone, of course.)

I would prefer to avoid a feature like this. The semantics are more
complex and ambiguous, as can be witnessed in Common Lisp. But if others
want it, I have nothing against adding it to R7RS-large and other
keyword SRFIs. Anything that can be made compatible is fine.

Can you explain to me in what sense the semantics are ambiguous?
 
A lot of my "keep it simple" advocacy comes from the perspective of
large programs. In a large program almost every feature is unfamiliar
and you don't have time to learn more than the basics. If the program is
written in a simple language, you can make more assumptions, freeing
more of your brain capacity for thinking about the program instead of
the language. This is one of my favorite things about Scheme.

I agree and still my conclusions seem to be different. :) The less artificial restrictions, the simpler the language. You may prove me wrong, but the concept of rest arguments seems to be orthogonal to the concept of keyword arguments as in SRFI 177.  It is an artificial restriction to have one exclude the other.
Marc