[racket] Bouncing default value

From: Eli Barzilay (eli at barzilay.org)
Date: Sat Feb 11 16:31:50 EST 2012

Four hours ago, Laurent wrote:
> (define (foo arg1 [arg2 <some-complicated-default-value>])
>   ....)
> (define (bar [arg2 <the-same-complicated-default-value>])
>   (foo 5 arg2))

Robby's suggestion is basically:

  (define (foo x [y #f])
    (let ([y (or y <some-complicated-default-value>)])

  (define (bar [y #f])
    (foo 5 y))

If #f is a valid value, the common way to deal with it is to have a
special value instead:

  (define none (gensym))

  (define (foo x [y none])
    (let ([y (if (eq? y none) <some-complicated-default-value> y)])

  (define (bar [y none])
    (foo 5 y))

A different way to resolve this is to accept all arguments and pass
them along:

  (define (foo x [y <some-complicated-default-value>]) ...)

  (define (bar . args) (apply foo 5 args))

and this gets a bit more complicated if you want to do the same for
keyworded functions too.

Or to have a more precise arity:

  (define bar
    (case-lambda [()  (foo 5)]
                 [(y) (foo 5 y)]))

A variant of this is what Rodolfo wrote, which can use the same none
value (useful if it's in a different module):

  (define none (gensym))
  (define (bar [y none])
    (if (eq? y none) (foo 5) (foo 5 none)))

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

Posted on the users mailing list.