Keywords reduced Lassi Kortela 18 Oct 2019 15:24 UTC

This is an attempt to reduce the problem to its core.

The thought process behind the SRFI (from first principles) is:

1. Practically every Scheme has syntax-rules or equally powerful macros.

2. Several Schemes have built-in kw args using CL-style kw objects.

3. Kawa and Racket have built-in kw args using kw as syntax markers.

4. Lambda definitions, and procedure calls, look identical in cases 2
and 3 (only with different #! #: : prefix/suffix) and can be generated
easily with macros in all of these implementations, so the
keyword-objects-vs-keyword-markers thing doesn't matter for portable macros.

5. Compatibility is all-important. If Scheme is to take off, we need
people to write a large mass of portable libraries. Library writers need
to be confident that they can reach for a portable solution when they
need it. This promise is less alluring with each additional gap in
compatibility. The easiest way to be fully compatible is to take the
common subset of the things that implementations are already doing.

6. Compatibility should be both ways: Portable code should be able to
call implementation-native keyword procedures using only RnRS read
syntax; and procedures using implementation-native keyword arguments
should be able to call keyword-lambdas defined by portable code. This
will be difficult to do without having the portable code use macros that
directly expand to the implementation-native syntax.

7. Simplicity for users is the next most important thing. Scheme is
attractive because of its small core. I'd like to add the bare minimum
amount to this core. It reinforces people's image of Scheme as a simple
language, and frees brainpower to be spent on libraries and
applications. This is why it's nice if keyword-lambda can be just like
lambda. Lambda is something people already know and like.

Fast code is also nice and led to a very interesting discussion. But
Scheme is very fast already :) I ran some benchmarks with the naive
plist implementation, and calling keyword procedures with no keywords
(i.e. null rest argument) is practically identical in speed to calling
non-keyword procedures. Calling with one or two keywords is 2-10x
slower, but you have to do like 100K calls per second for it to matter.
If native keyword args are used, it can potentially be equally fast to
using only positional args.

Since Marc and John care about fast calls, would you accept the current
compromise where the naive plist implementation is retained as the
"least common denominator" compatible option, and if faster keywords are
desired, the Scheme implementation is free to have a special calling
convention?

Thanks to everyone for all the thoughtful comments so far!