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

问题描述 投票:0回答:3

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

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

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

common-lisp
3个回答
8
投票

标准迭代结构中的多个值并不真正支持。

使用 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)
  ...)

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


7
投票

怎么样?:

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

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


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
更好。

© www.soinside.com 2019 - 2024. All rights reserved.