Capstone
Capstone

Reputation: 2282

Mutiple value bind in do loop in Common Lisp

How do you bind multiple values returned from a function, inside a do loop? The following is obviously very wrong, but is something like this possible?

(do (((x y z) (3-val-fn) (3-val-fn)))
    ((equal y 'some-val) y)
    (values x y z))

Or maybe there is a way to do this using multiple-value-bind?

Upvotes: 8

Views: 2514

Answers (3)

kennytilton
kennytilton

Reputation: 1064

How about?:

(loop for (x y z) = (multiple-value-list (3-val-fn))
 ...etc)

I'd offer more but cannot understand the do-loop.

Upvotes: 8

Rainer Joswig
Rainer Joswig

Reputation: 139261

Multiple values in the standard iteration constructs is not really supported.

With LOOP your snippet might look like this:

(loop with x and y and z
      do (setf (values x y z) (3-val-fn))
      while (equal y 'some-val)
      finally (return y)
      do ...)

If I would need something like that often, I might define a do-mv macro which would expand into above code. Code then would look like:

(do-mv ((x y z) (3-val-fn))
       ((equal y 'some-val) y)
  ...)

The advantage to use above is that it does not create lists from multiple values during each iteration. Creating lists out of multiple values kind of defeats the purpose of multiple values, which are there to return more than one values and allowing it to be implemented in an efficient way.

Upvotes: 10

Vatine
Vatine

Reputation: 21268

It's (sort-of) doable with do*:

(defun foo (n)
  (do* ((n n (1- n))
    (values (multiple-value-list (truncate 17 n))
        (multiple-value-list (truncate 17 n)))
    (result (first values) (first values))
    (remainder (second values) (second values)))
      ((< n 3) nil)
    (format t "Result: ~d, remainder: ~d, n: ~d~%" result remainder n)))

Here we first convert the multi-valued function result into a list, bind that to a variable and then manually destructure it. But it is hard to read and should probably be avoided, unless the do family of iteration constructs really happens to be a lot better choice than using loop.

Upvotes: 1

Related Questions