这是我生成笛卡尔积的代码:
(defun cartesian-product (LIST)
(LOOP FOR X IN LIST
NCONC
(LOOP FOR Y IN LIST
COLLECT (LIST X Y))))
我试着用这个输出一个笛卡尔积:
(defun cartesian-product-generator (CALLBACK LIST)
(LOOP FOR X IN LIST
NCONC
(LOOP FOR Y IN LIST
DO(FUNCALL CALLBACK (LIST X Y)))))
但是当我尝试用以下方法测试它时出现错误:
(cartesian-product-generator '(A B C))
Error: Too few arguments in call to #<Compiled-function cartesian-product-generator #x30200097E60F>:
1 argument provided, at least 2 required. While executing: cartesian-product-generator, in process listener(1).
我是 LISP 的新手,想知道为什么会出现错误以及如何修复此错误。最终,我想在每次函数调用时输出每个笛卡尔积。
例如,如果列表由 ((1 1) (1 2) (2 1) (2 2))
组成。
我想生成 (1 1)
。然后是(1 2)
。然后是(2 1)
。最后,(2 2)
。
最佳答案
您的第一个代码确实可以正常工作。
(defun cartesian-product (list)
(loop
for x in list
nconc (loop for y in list
collect (list x y))))
用 '(a b c)
调用它返回一个列表:
((A A) (A B) (A C) (B A) (B B) (B C) (C A) (C B) (C C))
您想避免构建列表并改用回调。 为了简化,首先尝试只打印元素而不是收集它们。
这意味着您不关心返回生成的值 取决于调用者:您只想生成它们并将它们打印为 一旦可用。
基本上,您可以将所有nconc
和collect
关键字替换为do
,并添加对print
的调用:
(defun cartesian-product (list)
(loop
for x in list
do (loop for y in list
do (print (list x y)))))
使用 '(a b c)
对 REPL 进行快速测试应该打印相同的内容
元素和以前一样,每个元素都在一个单独的行上。
现在,您可以概括 print
并调用您想要的任何内容:
(defun map-cartesian-product (function list)
(loop
for x in list
do (loop for y in list
do (funcall function (list x y)))))
只是为了看看它是否仍然有效,做一个快速测试:
(map-cartesian-product #'print '(a b c))
这应该具有与以前相同的行为。
因为你只是为了副作用而遍历一个列表,你可以使用
DOLIST
:
(defun map-cartesian-product (function list)
(dolist (x list)
(dolist (y list)
(funcall function (list x y)))))
同样,您可以测试它是否仍像以前一样工作。
关于loops - 如何在 lisp 中生成一个笛卡尔积?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49869728/