[plt-scheme] keyword arguments (in v4.0, maybe)
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.)
Completely new languages (like frtime, lazy, typed scheme, the new
servlet language) will probably need to use keyword wrappers in many
places too.
* 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.
* A popular use of wrappers is in testing 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. Also things
like "ffi/esd.ss" use apply for similar reasons.
* FrTime has `(apply apply fn args)' in several places. There is a
similar thing in "plot/fit.ss".
* `ext:wrap' from "web-server/private/response.ss"
* "make/setup-extension.ss" -- applies a given setup hook.
* 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.
* lazy/force.ss uses a wrapper when doing a "very deep" (!!!) force of
a value -- wraps functions so their results is forced.
* 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'.
* "web-server/web-server.ss" has code that calls a bunch of
callbacks+args -- `(for-each apply shutdowns)'
* `control-io-apply' from "setup/setup-unit.ss"
* "compiler/private/xform.ss" has some printf-wrappers, and some
trace-like wrappers.
* `make-closure-definition-syntax' from "web-server/private/closure.ss"
* `make-shared-array' from "srfi/63/63.ss" applies a provided `mapper'
* "srfi/25/arlib.scm" (and others) has a few mapping functions for
arrays
* `run' from "preprocessor/pp-run.ss" applies a given preprocessor
function
* "compiler/src2src.ss" applies an arbitrary mzscheme function for
constant folding
* `tree-apply' from "planet/private/planet-shared.ss"
* `mk-k' from "eopl/eopl.ss"; `sllgen:apply-reduction' from
"eopl/private/sllgen.ss"
* `output-form' from "swindle/html.ss" wraps a function for formatted
output, and the same uses lots of wrapping for a hierarchy of html
tag functions
* "swindle/misc.ss" defines `memoize'
* "swindle/base.ss" redefines `#%app' so `(foo x . r)' is the same as
`(apply foo x r)' -- this was one of my first hack that were only
because I was excited by the new module/syntax system. As
questionable as this is, it means that it's even more difficult to
find problematic code.
* "swindle/tiny-clos.ss" uses *lots* of `apply's for invoking
generics, slot access, etc etc etc.
* "swindle/misc.ss" defines `map!', `mappend', `mappend!', `mapply',
`some', `every',
* `for-each-snip' and `map-snip' from
"mrlib/private/aligned-pasteboard/snip-lib.ss"
* "srfi/1/..." defines `any', `every', `list-index', `count', `fold',
`fold-right', `pair-fold-right', `pair-fold', `reduce',
`reduce-right', `append-map', `append-map!', `pair-for-each',
`map!', `filter-map', `my-map', `my-for-each'
* "mzlib/list.ss" defines `foldl', `foldr'
* "mzlib/etc.ss" defines `compose'
* `consumer-thread' from "mzlib/thread.ss"
* `define-macro' from "mzlib/defmacro.ss"
* `default-sandbox-guard' wraps `(sandbox-network-guard)' to make that
function customizable (in "mzlib/sandbox.ss")
OK, I'm tired of this...
On Jun 12, Matthew Flatt wrote:
> > What would the expansion look like?
>
> The expression
>
> (lambda (x #:y y) (list x y))
>
> would expand to something like
>
> (make-keyword-procedure-with-info
> (lambda (kws x) (list a (cdar kws)))
> '(#:y) ; required
> '()) ; optional
>
> The expression
>
> (f 1 #:y 2)
>
> would expand to something like
>
> (let ([r f]
> [a1 1]
> [a2 2])
> (keyword-apply r (list (cons #:y a2)) a1))
Ooh, lots of consing... More in a followup message.
--
((lambda (x) (x x)) (lambda (x) (x x))) Eli Barzilay:
http://www.barzilay.org/ Maze is Life!