I feel this comparison is somewhat skewed. The typical
situation where I use multiple values is:
- multiple values are generated for every iteration,
so mm vs vv test is more close, and
- the expression body of generating multiple values are
known, so I'd rather use srfi-8's RECEIVE.
And this is the result on Gauche 0.8.6 / P4 2GHz (I use 100times
more iterations as William Clinger did.)
gosh> (time (for-each (lambda (x) ((mm x) list)) (make-list 10000000 1)))
; real 19.542
; user 19.480
; sys 0.060
gosh> (time (for-each (lambda (x) (call-with-values (lambda () (vv x)) list)) (make-list 10000000 1)))
; real 26.579
; user 26.460
; sys 0.110
gosh> (time (for-each (lambda (x) (receive z (vv x) (list z))) (make-list 10000000 1)))
; real 11.805
; user 11.750
; sys 0.040
The point is that the 'call-with-values' version creates
a closure for every iteration, as well as mu version, while
'receive' version can optimize it away. The same optimization
is done with srfi-11 let-values as well.
(If the optimizer is sufficienty smart, 'call-with-values'
version can also be compiled without creating closures,
given that the binding of 'call-with-values' itself is
not altered elsewhere.)
The difference of mu vs call-with-values did catch my
attention. There should be some room for improvement.
--shiro