Hello,
I wrote some code yesterday that used a few big WHICHEVER forms (with 30 or so possibilities) and that turned out to be a bit slow. The attached patch simplifies the implementation of WHICHEVER and its performance doesn't seem to degrade as the number of possibilities increases.
Here are both macro expansions for comparision:
CL-USER> (macroexpand-1 `(alexandria:whichever * * *)) (CASE (RANDOM 3) (0 *) (1 *) (2 *)) T CL-USER> (macroexpand-1 `(alexandria::whichever-old * * *)) (LET ((#:FUNCTION940 (LAMBDA () *))) (DECLARE #'#:FUNCTION940) (WHEN (ZEROP (RANDOM 2)) (SETF #:FUNCTION940 (LAMBDA () *))) (WHEN (ZEROP (RANDOM 3)) (SETF #:FUNCTION940 (LAMBDA () *))) (FUNCALL #:FUNCTION940)) T
Am I missing some advantage of the more complex implementation?
Some timings:
CL-USER> (compile nil `(lambda () (loop repeat 1000000 do (alexandria::WHICHEVER-OLD ,@(loop repeat 30 collect '*))))) #<FUNCTION (LAMBDA ()) {10037E64D9}> NIL NIL CL-USER> (time (funcall *)) Evaluation took: 0.937 seconds of real time 0.904057 seconds of total run time (0.904057 user, 0.000000 system) 96.48% CPU 2,498,021,856 processor cycles 558,368 bytes consed
NIL CL-USER> (compile nil `(lambda () (loop repeat 1000000 do (alexandria:WHICHEVER ; new version ,@(loop repeat 30 collect '*))))) #<FUNCTION (LAMBDA ()) {1002C1E069}> NIL NIL CL-USER> (time (funcall *)) Evaluation took: 0.033 seconds of real time 0.032002 seconds of total run time (0.032002 user, 0.000000 system) 96.97% CPU 89,029,912 processor cycles 288 bytes consed
NIL
The darcs patch might be too big for the list because the context goes all the way to the initial revision so I've uploaded it here: http://common-lisp.net/~loliveira/patches/alexandria-whichever.patch
Cheers,
alexandria-devel@common-lisp.net