[plt-scheme] passing-on keyword arguments

From: Eli Barzilay (eli at barzilay.org)
Date: Tue Mar 18 19:49:08 EDT 2008

On Mar 19, Jakub Piotr C?apa wrote:
> Eli Barzilay wrote:
> >   (define outer
> >     (make-keyword-procedure
> >      (lambda (kws vals . args)
> >        (+ (keyword-apply inner kws vals args) 5))))
> > 
> > I think that I know how to make it easier, allowing something like
> > this:
> > 
> >   (define (outer args ...)
> >     (+ (inner args ...) 5))
> > 
> > to do the same, but it'll take some work to implement.
> OTOH you loose all the information on what are the arguments to both
> inner and outer.

You don't lose any information about `inner' -- you just avoid
repeating its interface.

> Sooner than you think you got those Python *args, **kwargs functions
> all over the place

In these situations you already get these with plain scheme functions
-- it just happens that a single `*args' is needed.

I think that you can divide uses of rest arguments in Scheme to two:
using it with functions that accept any number of uniform arguments
(like `append', `+' etc), and less frequently in cases where (some of)
your arguments are really intended for another function.  The latter
are the problem here.  Two examples:

  ;; `sort-lists' is just like `sort', but it sorts a list of lists
  (define (sort-lists lists smaller?)
    (map (lambda (list) (sort list smaller?))))

The definition above is incorrect -- it hard-wires a specific `sort'
interface that might change.  Obviously, if `sort' actually changes,
then your code becomes broken -- but what if it's extended, for
example with an extra optional argument or keyword?

  ;; does a left- or right-fold
  (define (fold* direction fun init list)
    ((case direction
       [(left)  foldl]
       [(right) foldr])
     fun init list))

Again, I need to hard wire a specific interface to `foldl' and
`foldr', which is the same problem, but say that I want to generalize
this pattern:

  (define ((make-left-right fun-l fun-r) direction . args)
    (apply (case direction [(left) fun-l] [(right) fun-r])
  (define fold* (make-left-right foldl foldr))
  ;; srfi-1 things
  (define reduce* (make-left-right reduce reduce-right))
  (define take*   (make-left-rigth take   take-right))
  (define drop*   (make-left-rigth drop   drop-right))

This becomes impossible without some rest arguments.

> and runtime/editor documentation & reflection are worth nothing.

Huh?  My best guess is that you refer to the fact that `sort-lists'
does not have its own interface.  For that it would be nice to have
some way to say that its interface is exactly the interface of
`sort-lists'.  This is possible in PLT with `procedure-arity' etc, but
again not too convenient.  Keywords makes this problem harder, of

          ((lambda (x) (x x)) (lambda (x) (x x)))          Eli Barzilay:
                  http://www.barzilay.org/                 Maze is Life!

Posted on the users mailing list.