Am Di., 3. März 2020 um 17:48 Uhr schrieb Lassi Kortela <xxxxxx@lassi.io>:
>      >     (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.
>
>     I don't think I understand this. It only adds an `or`.

[My mistake: it adds a `let`, not an `or`.]

> You have one more local variable/indirection. The compiler needs to
> beta-reduce it.

I assumed that all but the simplest interpreters do that, but I don't
know that.

>      > 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.)
>
>     I'm not sure I agree that it's reasonable :)
>
> Why not? You may want to add a condition as an optional parameter.

Sure, but in that case I'd just use `condition` as the name. You may be
right that being able to use `cond` is better. A `:cond` keyword syntax
would solve the problem differently.

There are other common macros names like "when" or "unless" that would make sense as keyword names as well. "cond" was just an example:

(select a b c :when (lambda (x) (< x 5)))

How would the `:cond' keyword syntax solve the problem? How would the `lambda/kw' look in this case?

 
> If we argue with the simplicity and the beauty of Scheme, it should not
> matter which name the user chooses for their keyword arguments.
>
>     If identifier syntax is added Scheme, this would become quite
>     interesting.
>
> How is this related???

It could expand to a non-keyword. But since the call/kw macro containing
that identifier is expanded first, I guess it doesn't get to the point
where it would expand the identifier as syntax, so I was mistaken here.

>     That's why I'd like to have a simple and complex version of lambda/kw
>     (and define/kw) separately importable.
>
> What is the purpose of this? Apart from the fact that the version, which
> allows to choose the identifier names, is only an epsilon more
> complicated, this seems to be analogous to when you have `(scheme base)'
> exporting `assoc' without the optional third argument and `(scheme
> assoc)' exporting a version with the optional third argument.
>
> Users for which the third argument is too complicated to grasp can still
> use the three argument version, but just with two arguments.

The point is that R7RS-large and other SRFIs may end up adding more than
one optional feature to lambda/kw. If the full define/kw spec gets to
the CL/Racket complexity level, those are far from easy to read.

I understand that it makes sense to have basic SRFI and then, maybe, some fancy one building on the basic one.

But the basic SRFI should be somehow self-contained.
 

> The core of the Scheme language is very small. Keyword arguments would
> have to be added to this core that is to grasp.  Any programmer worth
> their name should at least have read and understood this core.

I don't agree with this. It's good that there are many programmers who
are more interested in writing applications than learning for the sake
of learning (as we are). They make valuable contributions to
programming, and also serve as a good benchmark for language design: if
a feature doesn't make them more productive, it may not be worth having.

There are still even parts of R7RS I haven't read in detail, and
whenever I write a syntax-case macro I need to check things from the spec.

Many experienced programmers eventually learn to work around the complex
parts of languages rather than learning them in detail. They learned
many complex things in detail before, and it wasn't always worth the
effort and led to complex code that was no more useful than simple code.
If programmers avoid complex features, it encourages language designers
to invent simpler ones. That sounds like a good thing to me.

Subsystems of the Scheme system should make it easier for programmers to grasp the language, and should not lead them up the garden-path.  If, say, SRFI 177's `lambda/kw' does conflate identifiers and symbols it makes it harder for newcomers to understand the difference.  Is there any other existing subsystem in R7RS-large that does this?  (Complexity is also increased if subsystems are not uniform in the way they treat things.)


> Scheme's raison d'être is that it is sufficiently different to other
> programming languages.

Definitely agreed. But one of the best ways in which it's different, is
that it's simpler and easier to remember :) These are worth preserving.

In a certain sense, Scheme could become simpler if we dropped, say, "let*" and "letrec" in favor of "let" and "letrec*" because it takes newcomers a moment to understand what the difference it.  But it would make Scheme less expressive. As much as Scheme is a programming language, it is also a language for algorithms and to reason about programs.