<div dir="ltr">I think I figured out the actual answer which is semantics. If the arguments are ever set!ed then my implementation will lead to a different value.<div><br></div><div style>(define (f a (b (begin (set! a 2) 3)))</div>
<div style>  a)</div><div style><br></div><div style>This should return 2 if b is not supplied, but in my expansion it would return what ever was supplied for a.</div></div><div class="gmail_extra"><br><br><div class="gmail_quote">
On Sun, Feb 24, 2013 at 11:14 AM, Matthew Flatt <span dir="ltr">&lt;<a href="mailto:mflatt@cs.utah.edu" target="_blank">mflatt@cs.utah.edu</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">At Sun, 24 Feb 2013 09:51:12 -0800, Eric Dobson wrote:<br>
&gt; lambda supports optional arguments, and does this by expanding out into a<br>
&gt; core form that has flag arguments for if each argument is supplied. This is<br>
&gt; tricky to type in TR and so I was investigating why it did it this way. I<br>
&gt; did a micro benchmark on another method of expansion and it was 60% faster.<br>
&gt; Is there a reason that racket does it the current way that I am missing.<br>
&gt;<br>
&gt; #lang racket<br>
&gt;<br>
&gt; (define f<br>
&gt;   (case-lambda<br>
&gt;     (() (f 1))<br>
&gt;     ((a) (f a (+ 3 a)))<br>
&gt;     ((a b) (f a b (* a b)))<br>
&gt;     ((a b c) (f a b c (- a (/ c b))))<br>
&gt;     ((a b c d) (+ a b c d))))<br>
&gt;<br>
&gt; (define (g (a 1) (b (+ 3 a)) (c (* a b)) (d (- a (/ c b))))<br>
&gt;   (+ a b c d))<br>
<br>
</div>I&#39;ll have to investigate more, but I don&#39;t think the story is simple.<br>
<br>
Below are the decompiled forms, and you&#39;ll see that they&#39;re essentially<br>
the same, due to inlining and other compiler optimizations.<br>
<br>
Part of the answer is probably how the different forms interact with<br>
inlining in the timing loops. If I change the code to<br>
<br>
 (define-values (f g)<br>
   (let ()<br>
     (define f ....)<br>
     (define g ....)<br>
     (values f g)))<br>
<br>
 (set! f f)<br>
 (set! g g)<br>
<br>
after the definition of `g&#39;, then performance is the same for the `f&#39;<br>
and `g&#39; (with a tiny difference that may be due to the order of clauses<br>
in `f&#39; and `g&#39;).<br>
<br>
You may also want to look at performance in the case that the eventual<br>
body cannot be inlined (e.g., because it&#39;s too large). Then, I think the<br>
chain of applications for `f&#39; will probably be significantly worse than<br>
the more direct implementation of `g&#39;.<br>
<br>
----------------------------------------<br>
<br>
    (define-values<br>
     (_f)<br>
     (case-lambda<br>
      (()<br>
       &#39;#(/private/tmp/c.rkt:5:4 #&lt;path:/private/tmp/c.rkt&gt; 5 4 44 10 #t)<br>
       &#39;(flags: preserves-marks single-result)<br>
       &#39;9)<br>
      ((arg0-12)<br>
       &#39;#(/private/tmp/c.rkt:6:4 #&lt;path:/private/tmp/c.rkt&gt; 6 4 59 19 #t)<br>
       &#39;(flags: preserves-marks single-result)<br>
       (let ((local13 (+ &#39;3 arg0-12)))<br>
         (let ((local16 (* arg0-12 local13)))<br>
           (+ arg0-12 local13 local16 (- arg0-12 (/ local16 local13))))))<br>
      ((arg0-27 arg1-28)<br>
       &#39;#(/private/tmp/c.rkt:7:4 #&lt;path:/private/tmp/c.rkt&gt; 7 4 83 23 #t)<br>
       &#39;(flags: preserves-marks single-result)<br>
       (let ((local29 (* arg0-27 arg1-28)))<br>
         (+ arg0-27 arg1-28 local29 (- arg0-27 (/ local29 arg1-28)))))<br>
      ((arg0-40 arg1-41 arg2-42)<br>
       &#39;#(/private/tmp/c.rkt:8:4 #&lt;path:/private/tmp/c.rkt&gt; 8 4 111 33 #t)<br>
       &#39;(flags: preserves-marks single-result)<br>
       (+ arg0-40 arg1-41 arg2-42 (- arg0-40 (/ arg2-42 arg1-41))))<br>
      ((arg0-51 arg1-52 arg2-53 arg3-54)<br>
       &#39;#(/private/tmp/c.rkt:9:4 #&lt;path:/private/tmp/c.rkt&gt; 9 4 149 23 #t)<br>
       &#39;(flags: preserves-marks single-result)<br>
       (+ arg0-51 arg1-52 arg2-53 arg3-54))))<br>
<br>
    (define-values<br>
     (_g)<br>
     (case-lambda<br>
      (() &#39;(flags: preserves-marks single-result) &#39;9)<br>
      ((arg0-59 arg1-60 arg2-61 arg3-62)<br>
       &#39;(flags: preserves-marks single-result)<br>
       (+ arg0-59 arg1-60 arg2-61 arg3-62))<br>
      ((arg0-67 arg1-68 arg2-69)<br>
       &#39;(flags: preserves-marks single-result)<br>
       (+ arg0-67 arg1-68 arg2-69 (- arg0-67 (/ arg2-69 arg1-68))))<br>
      ((arg0-78 arg1-79)<br>
       &#39;(flags: preserves-marks single-result)<br>
       (let ((local80 (* arg0-78 arg1-79)))<br>
         (+ arg0-78 arg1-79 local80 (- arg0-78 (/ local80 arg1-79)))))<br>
      ((arg0-91)<br>
       &#39;(flags: preserves-marks single-result)<br>
       (let ((local92 (+ &#39;3 arg0-91)))<br>
         (let ((local95 (* arg0-91 local92)))<br>
           (+ arg0-91 local92 local95 (- arg0-91 (/ local95 local92)))))))))<br>
<br>
<br>
</blockquote></div><br></div>