如何在lisp中生成一个笛卡尔积?

Mic*_*lle 1 lisp loops generator common-lisp cartesian-product

这是我生成笛卡尔积的代码:

(defun cartesian-product (LIST)
  (LOOP FOR X IN LIST
    NCONC
        (LOOP FOR Y IN LIST
         COLLECT (LIST X Y))))
Run Code Online (Sandbox Code Playgroud)

我尝试输出其中一个笛卡儿产品:

(defun cartesian-product-generator (CALLBACK LIST)
  (LOOP FOR X IN LIST
    NCONC
        (LOOP FOR Y IN LIST
        DO(FUNCALL CALLBACK (LIST X Y)))))
Run Code Online (Sandbox Code Playgroud)

但是当我尝试使用以下测试时出现错误:

(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).
Run Code Online (Sandbox Code Playgroud)

我是LISP的新手,想知道为什么会出现错误以及如何修复此错误.最终,我希望每次调用函数输出每个笛卡尔积.

例如,如果列表包含((1 1) (1 2) (2 1) (2 2)).我想生成(1 1).然后(1 2).然后(2 1).最后,(2 2).

cor*_*ump 6

您的第一个代码可以正常工作.

(defun cartesian-product (list)
  (loop
    for x in list
    nconc (loop for y in list
                collect (list x y))))
Run Code Online (Sandbox Code Playgroud)

调用它'(a b c)返回一个列表:

((A A) (A B) (A C) (B A) (B B) (B C) (C A) (C B) (C C))
Run Code Online (Sandbox Code Playgroud)

您希望避免构建列表并使用回调.为简化起见,首先尝试仅打印元素而不是收集它们.

这意味着您不必关心将生成的值返回给调用者:您只想生成它们并在它们可用时立即打印它们.

基本上,您可以替换所有nconccollect关键字do,并添加一个调用print:

(defun cartesian-product (list)
  (loop
    for x in list
    do (loop for y in list
             do (print (list x y)))))
Run Code Online (Sandbox Code Playgroud)

对REPL的快速测试'(a b c)应该打印与之前相同的元素,每个元素都在separte行上.

现在,您可以概括print并调用您想要的任何内容:

(defun map-cartesian-product (function list)
  (loop
    for x in list
    do (loop for y in list
             do (funcall function (list x y)))))
Run Code Online (Sandbox Code Playgroud)

只是为了看它是否仍然有效,做一个快速测试:

(map-cartesian-product #'print '(a b c))
Run Code Online (Sandbox Code Playgroud)

这应该具有与以前相同的行为.

由于您只迭代一个副作用列表,您可以使用 DOLIST:

(defun map-cartesian-product (function list)
  (dolist (x list)
    (dolist (y list)
      (funcall function (list x y)))))
Run Code Online (Sandbox Code Playgroud)

同样,您可以测试它仍然像以前一样工作.