Common Lisp中do循环中的多个值绑定

时间:2017-01-13 06:10:09

标签: common-lisp

如何在do循环中绑定函数返回的多个值? 以下显然是非常错误的,但这可能是这样吗?

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

或者也许有一种方法可以使用多值绑定来实现这一点?

3 个答案:

答案 0 :(得分:6)

实际上不支持标准迭代结构中的多个值。

使用LOOP,您的代码段可能如下所示:

(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 ...)

如果我经常需要这样的东西,我可能会定义一个do-mv宏,它将扩展到上面的代码中。然后代码看起来像:

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

上面使用的优点是它不会在每次迭代期间从多个值创建列表。用多个值创建列表会破坏多个值的目的,这些值可以返回多个值并允许以有效的方式实现它。

答案 1 :(得分:1)

怎么样?:

((x y z)的循环=(多值列表(3-val-fn))      ...等)

我会提供更多,但无法理解do-loop。

答案 2 :(得分:1)

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)))

这里我们首先将多值函数结果转换为列表,将其绑定到变量然后手动对其进行解构。但它很难阅读,应该可以避免,除非do迭代构造系列确实是比使用loop更好的选择。