首页 > 解决方案 > Common LISP:制作你自己的联合函数

问题描述

我正在尝试创建自己的联合功能并意识到我多么不喜欢 LISP。目标是给函数两个列表,它将返回两者的集合理论并集。我尝试的解决方案变得越来越复杂,结果相同:NIL。无论我做什么,我都无法改变结果。

我正在考虑在下面的“removeDuplicates”函数中建立一个单独的列表,但后来我想知道如何通过递归返回它。我认为发生的事情是我的“removeDuplicates”函数最终返回一个空列表(如预期的那样),但是当递归展开(开始返回堆栈的值)时,堆栈的每一级都会返回一个空列表,但我可能是错的。我一直无法详细理解递归。代码如下。

(defun rember (A LAT)
  (cond
   ((null LAT) ())
   ((EQ (car LAT) A) (cdr LAT))
   (T (cons (car LAT)(rember A (cdr LAT))))
   )
  )

(defun my_member (A LAT)
  (cond
   ((null LAT) nil)
   ((EQ (car LAT) A) T)
   (T (my_member A (cdr LAT)))
   )
  )

(defun removeDuplicates (L)
  (cond
   ((null L) '())
   ((my_member (car L) (cdr L)) (rember (car L) L) (removeDuplicates (cdr L)))
   (T (removeDuplicates (cdr L)))
   )
  )

(defun my_union (A B)
  (setq together(append A B))
  (removeDuplicates together)
  )

我知道大多数人不喜欢这种 LISP 代码格式,但我更喜欢它。与将所有右括号放在一起放在函数和条件块的末尾相比,它可以让我看到括号如何排列更好。

(my_union '(a b) '(b c))例如,如果我运行,结果为 NIL。

标签: lispunion

解决方案


当您removeDuplicates在最后一个条件下递归调用时,您不会将结果与car列表的 组合,因此您将丢弃该元素。

您也没有使用rember.

(defun removeDuplicates (L)
  (cond
   ((null L) '())
   ((my_member (car L) (cdr L)) 
    (cons (car L) 
          (removeDuplicates 
           (rember (car L) (cdr L)) 
           ))
    )
   (T (cons (car L) (removeDuplicates (cdr L))))
   )
  )

推荐阅读