[plt-scheme] keyword arguments (in v4.0, maybe)
At Tue, 12 Jun 2007 13:12:04 -0400, Eli Barzilay wrote:
> On Jun 12, Matthew Flatt wrote:
> >
> > So probably `procedure?' should return #f for things that are like
> > procedures, but that require some keyword (as opposed to things that
> > work like procedures and accept keyword-based arguments, but all the
> > keyword arguments all optional). Then, the above remains true for
> > procedures.
> >
> > Meanwhile, it's true that there's a kind of infection to the design,
> > in that many tools and libraries should be made to work with both
> > procedures and keyword-requiring things. But maybe working only for
> > procedures (that don't require any keywords) is a reasonable
> > specification for other tools and libraries.
> >
> > What examples do we have, other than `trace'?
>
> I grepped the PLT tree for other examples. This is a summary of
> things I found. (Some of these don't apply, some might apply in the
> future. I'm just trying to provide a quick overview, not a proper
> analysis.)
>
> * Definitions like
> (define (oprintf . args) (apply fprintf o args))
> would need to change if `fprintf' is extended (even if kwds are
> optional, since the intention is to have `oprintf' be the same as
> `fprintf'). I can see several additional builtin candidates for
> keywords. (The infection-aspect of this is visible in that after
> the above extension, uses of this `oprintf' in `apply' will need to
> be extended too.)
True, if keywords are going to be used with `oprintf'. This seems like
a trivial change to a local, internal function, and it can be made as
needed.
> 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.
> * There is another aspect to this problem -- back when we were
> discussing keyword arguments, one important feature I talked about
> is that they should make it easy to extend an existing definition in
> a way that does not require changing all call sites. The change in
> `apply' violates this -- if you extend `fprintf' with keywords, you
> will have to inspect and possibly modify all uses of it in `apply'.
> And BTW, it doesn't help that you're looking for uses that involve
> `apply' only -- since you don't know how values move around.
No, you misunderstand. A keyword-accepting procedure that doesn't
*require* a keyword argument is still a procedure that works with
`apply'.
So, it's pretty much always ok to add an optional keyword argument.
(The only exception I can think of is if some code uses
`keyword-procedure-arity' to determine exactly what keywords are
allowed. But that's the same obscure class of problems as adding an
optional non-keyword argument.)
> * A popular use of wrappers is in testing code.
Ok. Presumably if you need to add tests for keywords, then you don't
mind updating the test code.
> * The foreign interface uses function wrappers for custom C types (but
> does not use `apply'). Related: `do-fit' from
> "plot/fit-low-level.ss" applies a provided callback.
It's used with procedures that are known not to have keyword arguments.
> Also things
> like "ffi/esd.ss" use apply for similar reasons.
Ditto.
> * FrTime has `(apply apply fn args)' in several places.
That's the implementation of `frp:apply'! I assume that it doesn't need
to change if `apply' doesn't change.
> There is a
> similar thing in "plot/fit.ss".
Again, I'm pretty sure that a non-keyword function is required for
other reasons, so this one is fine.
> * `ext:wrap' from "web-server/private/response.ss"
Again, the contracts say that the relevant function must have
particular shape, and that shap doesn't include keywords.
> * handin-server/private/reloadable.ss -- installs a function wrapper
> for auto-reloading code; .../private/run-status.ss -- applies a
> messenger value (taken from a parameter); .../utils.ss applies a
> checker procedure.
Ah, an interesting example, at last!
Yes, this probably need to change.
> * lazy/force.ss uses a wrapper when doing a "very deep" (!!!) force of
> a value -- wraps functions so their results is forced.
I can't tell in this code.
> * In class code, (apply super-init args) is often used (not a problem
> while class initialization uses it's own keyword mechanism, which I
> think would be nice to change eventually). Same goes for a future
> extension of `make-object' and `struct-type-make-constructor'.
The class system would need to change to support keyword-based methods,
anyway.
> * "web-server/web-server.ss" has code that calls a bunch of
> callbacks+args -- `(for-each apply shutdowns)'
This code is explicitly using keywords, so it would certainly have to
change.
> * `control-io-apply' from "setup/setup-unit.ss"
It's internal and only used with a non-keyword procedure.
> * "compiler/private/xform.ss" has some printf-wrappers, and some
> trace-like wrappers.
Again, internal.
> * `make-closure-definition-syntax' from "web-server/private/closure.ss"
I don't know about this one.
> * `make-shared-array' from "srfi/63/63.ss" applies a provided `mapper'
Another case where the calling convention of the given function is
explicitly contrained.
> * "srfi/25/arlib.scm" (and others) has a few mapping functions for
> arrays
Ditto.
> * `run' from "preprocessor/pp-run.ss" applies a given preprocessor
> function
To known arguments (i.e., not keywords).
Maybe you can finish out the list for me. It should be clear from the
above that the problem is nowhere near as great as you're suggesting.
There are some issues with the change:
* There's an upgrade issue with procedures and tools that work with
both unknown procedures and unknown sets of arguments. (That's
actually a small slice of the uses of `apply'.)
* There's also an issue with implementing new languages, if the
languages have anything to do with keywords.
* There's a potential issue with converting any existing code that
uses keywords.
These kinds of things are in line with other changes that we try,
though.
Matthew