[plt-scheme] keyword arguments (in v4.0, maybe)
On Jun 12, Eli Barzilay wrote:
> [...]
So far, I have two big problems with the new suggestion.
1. Due to the `apply' problem, changing a function to use keywords
means that you need to scan and possible change all call sites.
This is the same problem that will make using portable code much
more difficult -- which will make using this keyword-argument
device much less popular than it should be.
In some previous discussion about keyword arguments, I had this as
my main constraint on any keyword facility -- it must be easy to
add keywords to an existing function with no additional changes.
Matthias summarized it much nicer -- the problem is that adding
keywords to a function definition is a backward-incompatible
change.
2. Another property that I mentioned earlier is that it should be as
lightweight as possible. Paying the price to do keywords searches
etc is fine (of course, using code that does not add unnecessary
price), but the new proposal suffers in two places: (a) it uses a
lot of allocation -- as in the previous message, this is both in
(wrapper) function definitions and in function calls; (b) it looks
like wrapper functions will have some penalty too.
The first one is problematic, since it also will drive people away
from using keyword args. The second is very bad -- given the
code-infection property, it means that lots of code will need to
pay the price. I can see myself replicating mzlib code just
because I want to suck every cpu cycle for some program...
Here's an alternative proposal:
* The core language is left as-is, minus self-quoting keywords. This
means that if you call
(+ 1 2 '#:foo 3)
you still get an error, but it should not be any worse than using
any other non-numeric type. #:foo by itself is still a syntax
error. The extra punctuation still has the good effect of
discouraging keywords where symbols can do.
* The higher-level language (I don't remember if it was `big' or
`large') redefines `#%app' so that you can have unquoted keywords.
It can also do some of the syntax-time operations that were
discussed, like ordering keywords, moving them all to the end,
detecting multiple keywords and value-less keywords etc etc.
* This covers most of the benefits of the original design, but not
all. For example, in this language, you can still do
(+ 1 2 #:foo 3)
and not get an error; and you can be surprised that:
(list #:foo 1 2 3)
produces (2 3 #:foo 1). These problems happen only when you use an
unquoted keyword for a non-keyword function.
* Side advantage: existing code can be used, perhaps with removing
some of the exotic things that "kw.ss" can do.
The above seems to me to be a resonable compromise: it doesn't cover
all errors, but it is *much* better (IMO) than keyword-ifying being a
backward-incompatible change. Looking back at the original two
problems that Matthew mentioned:
> (greet #:last "Doe")
greet: expecting a (#:last #:hi) keyword got: "Doe"
> (greet "John" #:hi #:last "Doe")
greet: expecting a (#:last #:hi) keyword got: "Doe"
The first one is still a problem, but the second one is also a syntax
error. (Still, I prefer this over breaking code in the original
design.)
[
I'm not sure how this can be solved both sanely and efficiently.
Perhaps make this:
(greet "John" #:last "Doe")
expand to
(greet "John" keyword-value-marker #:last "Doe")
where that marker is a unique value, or an instance of a unique
struct? (This is bad because `greet' will need to check each of its
positional arguments to make sure that they're not the marker.) Maybe
expand that to something like
(apply greet "John" (make-keyword-args '(#:last "Doe")))
and extend `apply' to work on improper lists where the last value is a
keyword-args instance? (This is also suffering from the
incompatibility problem -- `(lambda xs (list? xs))' can return #f, but
it feels less invasive as the original suggestion.)
Or maybe expand to
(greet (make-keyword-args '(#:last "Doe")) "John")
(But this leads to confusing errors when passing keyword arguments to
a procedure that does not expect them.)
]
--
((lambda (x) (x x)) (lambda (x) (x x))) Eli Barzilay:
http://www.barzilay.org/ Maze is Life!