Re: or and values
Steve Haflich <[email protected]> Tue, 17 Oct 2006 14:06:52 -0700
| Newsgroups | gmane.lisp.allegro |
|---|---|
| Message-ID | <8218.1161119212@bach> |
From: Harley Gorrell <[email protected]> I think that was done so implementations could have a simple "or". You would get a better response from c.l.l. "Simple" is not quite the right consideration. Dropping multiple values from various compound forms is an important efficiency issue. Note that your macro below must cons a multiple values list in a way that most implementations cannot stack cons. The original poster's reluctance Is there a way to get all the values of the first form returning a non nil primary value? (without using conditionals and local variables) to use conditional and temporary values is not really where the proiblem is, since lexical variables in CL do not have any intrinsic cost and merely serve to name a value that flows from a computational source to a computational sink. Conditionals are also not an issue, since _some_ choice has to be made by the form, and the conditionals are safely hidden from the user programmer's eyes inside the macroexpansion. However, consing a list of arbitrary unknown length may have performance cost. Note the multiple-value-list in the macro below Not that I know of. One can be written though. (defmacro or-mvl (&rest args) (or-mvl-1 args)) (defun or-mvl-1 (args) (let ((arg (car args)) (sym (gensym))) `(let ((,sym (multiple-value-list ,arg))) (if (car ,sym) (values-list ,sym) ,(if (cdr args) (or-mvl-1 (cdr args)) nil))))) This can be avoided, but only with real gymnastics that likely has a different performance cost. I believe the following will compile cons free in ACL under sufficient optimization. (defmacro ormv (&rest forms) (let ((blk (gensym)) (fnc (gensym))) `(block ,blk (flet ((,fnc (&rest args) (declare (dynamic-extent args) (optimize speed (safety 0))) (and args (car args) (return-from ,blk (apply #'values args))))) (declare (dynamic-extent ,fnc)) ,@(mapcar (lambda (form) `(multiple-value-call #'fnc ,form)) forms))))) It exploits the ability of the compiler to stack cons a &rest list to avoid heap consing, but it does have the overhead of establishing a catch on the stack (to implement the block/return-from). This is cons free, but does cost cycles...