我是 Lisp 的新手,我遇到了以下问题。
我正在尝试交换多个列表中的数字并生成一个列表列表作为结果,以便每个列表中第一个数字的所有数字都将收集在一个列表中,该列表是第一个元素结果列表;并且每个列表中排名第二的所有数字将被收集在另一个列表中,该列表是结果列表的第二个元素;等等。
这是一个例子:
(foo '((3 4 2 4) (2 5 6 9) (1 -2 8 10)) )
=> ((3 2 1) (4 5 -2) (2 6 8) (4 9 10))
我目前的解决方案是这样的:
(defun foo (list)
(mapcar #'list (values-list list))
)
据我所知,values-list
应该返回给定参数 list
中的所有子列表。然后 mapcar
将遍历每个子列表的每个元素并将它们制成一个列表。
第二部分有效,但是只使用了第一个子列表,导致 ((3) (4) (2) (4))
而不是 (( 3 2 1) (4 5 -2) (2 6 8) (4 9 10))
。
这是为什么?
(我正在使用 CLISP)。
最佳答案
在你的代码中
(defun foo (list)
(mapcar #'list (values-list list)))
values-list
将列表作为多个值返回。但是您调用的是像 mapcar
这样的函数,而普通的函数调用每个参数只需要一个值。
要修复它,您可以通过 multiple-value-call
调用 mapcar
:
CL-USER 47 > (defun foo (list)
(multiple-value-call #'mapcar #'list (values-list list)))
FOO
CL-USER 48 > (foo '((3 4 2 4) (2 5 6 9) (1 -2 8 10)) )
((3 2 1) (4 5 -2) (2 6 8) (4 9 10))
然后上面会将所有值传递给mapcar
。
请注意,参数列表在 Common Lisp 实现中是有限的。请参阅变量 call-arguments-limit
。只能确定小于 call-arguments-limit
参数的函数调用在给定的 Common Lisp 实现中有效。
因此,对于具有无限长度列表的列表处理,不应依赖于 apply
或 multiple-value-call
等功能。
使用多个值
Common Lisp 支持多值作为一种优化。它允许一个人返回多个值,而无需为其构造数据结构。
通常函数每个参数只接收单个值。
所有与多值相关的事情都是通过运算符完成的:values
返回值,multiple-value-bind
接收值并将它们绑定(bind)到变量,...然后是多值调用
,值列表
,多值限制
,多值列表
, multiple-value-setq
, (setf (values ...) ...)
, multiple-value-prog1
, nth -值
。
关于list - 为什么 mapcar 只使用从值列表返回的参数之一?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59307111/