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