[plt-scheme] keyword arguments (in v4.0, maybe)

From: Matthew Flatt (mflatt at cs.utah.edu)
Date: Wed Jun 13 10:51:40 EDT 2007

At Wed, 13 Jun 2007 01:01:44 -0400, Eli Barzilay wrote:
> On Jun 13, Matthew Flatt wrote:
> > At Tue, 12 Jun 2007 13:12:04 -0400, Eli Barzilay wrote:
> > > 
> > >   Completely new languages (like frtime, lazy, typed scheme, the
> > >   new servlet language) will probably need to use keyword wrappers
> > >   in many places too.
> > 
> > Yes, that makes sense.
> This brings the efficiency re allocation to a more important status --
> if writing a wrapper for a possibly-keyworded function degrades
> performance, then these languages can suffer from a global slowdown.

That's not obvious to me. I think the explicit distinction between
keyword-based applications and non-keyword applications will tend to
other languages as much as it does Scheme.

> 1. I write
>       (define (foo x) ...)
> 2. I use it with some wrapper using code (in this case it's Swindle's
>    `memoize'):
>       (define mfoo (memoize foo))
> 3. I generalize `foo' and add an optional keyword argument:
>       (define (foo x #:y [y "wie"]) ...)
> 4. `mfoo' is now not a memoized version of `foo' -- it's only a
>    memoized version of it when there are no keywords given.
> 5. That was a good case -- if I had added a required keyword argument:
>       (define (foo x #:y y) ...)
>    then `mfoo' would be a useless function that throws an exception if
>    given keywords (since `mfoo' does not want them), or if not given
>    keywords (since `foo' requires them).
> 6. I mail the Swindle author, he replies that he likes to write
>    portable Scheme code so the code runs with SuperScheme's amazing
>    compiler.  After some flaming it's clear that I'm on my own.
> 7. I copy the Swindle code, and make it work for keyworded functions.
> 8. A year later Swindle gets improved with the new zumba-hashing
>    algorithm that makes `memoizate' 10 times faster.  My code is not
>    not in sync...

This is true --- but it doesn't seem like a likely scenario. Aren't you
about 100 times more likely to run into trouble mixing libraries if we
start encouraging immutable cons cells? Aren't you about as likely to
want to memoize method results as well as procedures?

> Another example of this: `-get-file' and `-put-file' from the end of
> "framework/private/finder.ss" wrap some functions that currently do
> not accept keyword values.  When these functions are updated, the call
> site in `-get-file' and `-put-file' should be updated too.

Yes. There will be a few things like this, and I think we can handle

> Another point for consideration -- the symmetric multiple-values-in
> and -out is gone, so `(compose f g)' cannot pass keyword args to `f'.

I don't see any technical problem with with a `call-with-values' that
works with keyword-procedure recieves and a `values/keywords' for
returning multiple values. That seems really unlikely to be useful, but
it's possible.

> * You also missed the `memoize' thing above

You're right: if we had a general memoize, then it falls into the
category of general tools that we'd have to fix up.

> * Also, I mentioned the curry thing, for example a simple two-stage
>   currify:
>     (define (currify f)
>       (lambda args1 (lambda args2 (apply f (append args1 args2)))))

This too.

> * Some of the things that i mentioned are a problem, here's a random
>   one:
>   | > * `control-io-apply' from "setup/setup-unit.ss"
>   | 
>   | It's internal and only used with a non-keyword procedure.
>   The problem is that if any of the functions that are fed to this is
>   extended to use keywords, then this needs to be updated too.  If
>   it's not, then it wraps a less useful (perhaps completely useful)
>   version of the input function.

To be clear, there is one call of `control-io-apply', it is called with
one specific function, and the actual arguments are with the
`control-io-apply' call.

So, this falls in the large category of "things that would have to
change if we changed them to involve keywords". I don't worry too much
about having to change something that I've decided to change.

> * lang/private/contracts/contracts-helpers.ss:144

If contracts support keyword arguments, then this is just the tip of
the iceberg. Yes, some parts of the language will have to change.

> * lang/prim.ss:24 (my guess is that this will need to change if
>   keyword procs are used in the teaching languages)

Again, if we add keyword arguments to the teaching languages, this is
just the tip of the iceberg.

I can't imagine adding keyword arguments to the teaching languages,
though, so there's no point in worrying about this one.

> * mztake/engine.ss:145, mztake/engine.ss:166 (similar to tracing, I
>   guess); mztake/mztake.ss:51 (not sure about that one)

Unlikely, since mztake works on expanded programs.

> * mztake/annotator.ss:88, mztake/annotator.ss:93 (not sure about this,
>   but annotators like mztake's or the stepper will need to change)


> * htdp/big-draw.ss:73, htdp/big-draw.ss:119, htdp/big-draw.ss:178
>   (looks like they will need to change if used with keyword
>   procedures)

Yes, if we change "big-draw.ss" to export a keyword API, then we have
to change "big-draw.ss"...

> * tests/mred/item.ss:309 (few similar cases in this file)
> * tests/mred/random.ss:849
> * tests/stepper/through-tests.ss:92
> * tests/mzscheme/number.ss:259 (many other tests, I think that I
>   mentioned tests earlier)

Lots more similar examples. If we change a procedure to take keyword
arguments, then we have to change the local helper functions used to
test, along with the tests. I fail to see the concern here.

> * browser/external.ss:59

Yes, this is like `-get-file'.

> * mred/private/app.ss:65

This would need to change iff the MrEd API changes, so I see no

> * mzlib/deflate.ss:75

This is an extreme example of private code (debugging instrumentation).

So, I count 3-4 out of the 15 bullets above that are remotely likely to
be an issue, and that's after you've filtered a lot of code. It seems
very much in line with the other sorts of changes that we make once in
a while.

In any case, I've clearly explained the idea badly, and I plan to start
over tomorrow. We've ended up in a small corner of the space, talking
about very general functions that aspire to accommodate anything
callable. We're not talking about the part that I think matters, which
is the broader, helpful role that keywords can play if we de-tangle
them from expressions.


Posted on the users mailing list.