Re: Keyword arguments in procedures specified in SRFIs
Lassi Kortela 22 Jul 2019 09:07 UTC
Thank you for clearly outlining the solutions.
> 1) A backwards incompatible change to Scheme's syntax by which certain
> symbols are no longer treated as identifiers but as self-quoting
> datums. If we do that, we might as well allow both :foo and foo: with
> exactly the same meaning.
>
> 2) Adding a wholly new syntax for self-quoting datums that does not
> overlap with the syntax for identifiers, in which case #:foo is the
> natural syntax.
>
> 3) We could make #:foo not an expression at all, but part of the syntax
> of procedure calls. In that case, #:foo would be a datum but not an
> expression, whereas '#:foo would be both.
>
> All this is quite independent of how keywords would actually be used in
> procedure definitions, which could be managed in a variety of ways.
Indeed, if we pick approach 1 or 2 then we don't have to say anything
about procedure definitions. That would make our job a lot easier. The
spec could just talk about keyword objects and syntax for them, and
leave the parsing of keyword arguments to some future spec once we have
rested a bit from this effort :)
Meanwhile, Scheme programmers could already start to use the consing dot
to append a property list of keyword arguments to their positional args:
(define (foo a b c . kwargs)
(let-values (((d e f) (parse-kwargs kwargs d: e: f:)))
(list a b c d e f)))
(foo 1 2 3 e: 4 f: 5 d: 6)
where (parse-kwargs) would just be a procedure from that particular
programmer's favorite library. The calling convention would not be
optimized by the implementation, but keyword args are most urgently
needed in big procedures that do so many things that they don't need to
run fast anyway (the performance is I/O bound or the inner loops are
factored off into smaller procedures that don't take keyword arguments).
> Speaking with my editor's hat /off/, I don't like the idea of the
> inevitable complexity that would result.
Thanks for looking out for the interests of simplicity :)
Like John I find the complexity reasonable. It does seem weird to have
three different syntaxes for the same task, and reader flags for
toggling them, but every language community has historical baggage like
that. We just have to take it in stride. If Scheme wants to seriously
tackle the issue of writing big portable programs, we need to move
forward with keyword args as a community (at least I don't see a way
around it; I'll listen to arguments to the contrary). Of course, if
implementors want to agree on one keyword syntax right away, that would
be terrific. It just seems easier to provide a transitional option that
makes the existing approaches interoperate.
Now, how to _eventually_ get the community to favor one keyword syntax
over others is a very good question. I fully agree with you that that's
definitely a worthy goal. One way to tackle this would be to add one
(and only one) keyword syntax to R7RS-large. That would send a strong
signal. Meanwhile, implementations that support R7RS-large could also
opt to implement the compatibility SRFI that provides all of the
syntaxes, giving more transitional options for their users. How does
this sound?
> Getting Schemes that don't support either 1 or 2
> to accept either or both would be hard, as it involves completely new
> lexical syntax as well as a new primitive type.
I think this is fine. Tiny Schemes can opt to go with R7RS-small and no
keyword objects of any kind if it makes sense for their niche. Lack of
keywords doesn't really matter when writing small programs, for which
those Schemes are well suited.