Thank you all for your good and helpful answers.<div>Based on them, here is my current solution (without keywords), using macros to ease the function definition:</div><div><br></div><div><br></div><div><div>#lang racket</div>

<div><br></div><div>(define default (gensym))</div><div>(define (default? x) (equal? x default))</div><div><br></div><div>(define-syntax parse-args-body</div><div>  (syntax-rules ()</div><div>    ; we found the optional arguments</div>

<div>    [(_ ((arg-opt val) ...) body ...)</div><div>     (let ([arg-opt (if (default? arg-opt) val arg-opt)]</div><div>           ...)</div><div>       body ...)]</div><div>    ; the first arg is not optional, parse the rest</div>

<div>    [(_ (arg1 arg2 ...) body ...)</div><div>     (parse-args-body (arg2 ...) body ...)]</div><div>    ; no optional arg found</div><div>    [(_ () body ...)</div><div>     (begin body ...)]</div><div>    ))</div><div>

<br></div><div>;; The (opt-arg val) are not turned into (opt-arg default) </div><div>;; because there is no real need to, and I tried and it was surprisingly non-trivial (means: couldn&#39;t do it)</div><div>;; (because the parsing needs to be done *before* the define)</div>

<div>(define-syntax-rule (define/default (f arg ...) body ...)</div><div>  (define (f arg ...)</div><div>    (parse-args-body (arg ...) body ...)</div><div>    ))</div><div><br></div><div>;#| TESTS</div><div><br></div><div>

(define/default (f arg1 [arg2 3])</div><div>  (list arg1 arg2))</div><div><br></div><div>(f 1) ; -&gt; &#39;(1 3)</div><div>(f 1 default) ; -&gt; &#39;(1 3)</div><div>(f 1 &#39;smthg) ; -&gt; &#39;(1 smthg)</div><div><br>

</div><div>;|#</div></div><div><br></div><div>That&#39;d be nice if all functions were implemented with something like that, so that the default symbol can be used without needing to know the actual value.</div><div><br>
</div>
<div><br></div><div>Laurent</div><div><br></div><div><br><br><div class="gmail_quote">On Sat, Feb 11, 2012 at 22:31, Eli Barzilay <span dir="ltr">&lt;<a href="mailto:eli@barzilay.org">eli@barzilay.org</a>&gt;</span> wrote:<br>

<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div class="im">Four hours ago, Laurent wrote:<br>
&gt;<br>
&gt; (define (foo arg1 [arg2 &lt;some-complicated-default-value&gt;])<br>
&gt;   ....)<br>
&gt;<br>
</div><div class="im">&gt; (define (bar [arg2 &lt;the-same-complicated-default-value&gt;])<br>
&gt;   (foo 5 arg2))<br>
<br>
</div>Robby&#39;s suggestion is basically:<br>
<br>
  (define (foo x [y #f])<br>
    (let ([y (or y &lt;some-complicated-default-value&gt;)])<br>
      ...))<br>
<br>
  (define (bar [y #f])<br>
    (foo 5 y))<br>
<br>
If #f is a valid value, the common way to deal with it is to have a<br>
special value instead:<br>
<br>
  (define none (gensym))<br>
<br>
  (define (foo x [y none])<br>
    (let ([y (if (eq? y none) &lt;some-complicated-default-value&gt; y)])<br>
      ...))<br>
<br>
  (define (bar [y none])<br>
    (foo 5 y))<br>
<br>
A different way to resolve this is to accept all arguments and pass<br>
them along:<br>
<br>
  (define (foo x [y &lt;some-complicated-default-value&gt;]) ...)<br>
<br>
  (define (bar . args) (apply foo 5 args))<br>
<br>
and this gets a bit more complicated if you want to do the same for<br>
keyworded functions too.<br>
<br>
Or to have a more precise arity:<br>
<br>
  (define bar<br>
    (case-lambda [()  (foo 5)]<br>
                 [(y) (foo 5 y)]))<br>
<br>
A variant of this is what Rodolfo wrote, which can use the same none<br>
value (useful if it&#39;s in a different module):<br>
<br>
  (define none (gensym))<br>
  (define (bar [y none])<br>
    (if (eq? y none) (foo 5) (foo 5 none)))<br>
<span class="HOEnZb"><font color="#888888"><br>
--<br>
          ((lambda (x) (x x)) (lambda (x) (x x)))          Eli Barzilay:<br>
                    <a href="http://barzilay.org/" target="_blank">http://barzilay.org/</a>                   Maze is Life!<br>
</font></span></blockquote></div><br></div>