我正在尝试通过添加到空列表来构建一个唯一的元素列表,使用LISP中的以下代码:
;;;MEMSET - return T if an atom is a top-level member of a set, else NIL
;;;This is needed for the makeset function
(DEFUN MEMSET (ATM L)
(COND ( ( NULL L) NIL )
( (EQL ATM(CAR L)) T )
( T (MEMSET ATM (CDR L)) )
)
)
(DEFUN MAKESET(SET1)
(DO ((UNIQ ()))
( (NULL SET1) UNIQ)
(COND ( (NOT (MEMSET (CAR SET1) UNIQ))
(CONS (CAR SET1) UNIQ)
)
)
(SETF SET1 (CDR SET1))
)
)
Run Code Online (Sandbox Code Playgroud)
当我调用(makeset'(abbacdba))时,这个特殊的代码会产生NIL - 它应该导致(abcd),而不考虑顺序) - 但它看起来像我应该从SET1中添加一个原子而不是但在UNIQ每次迭代.你能不能添加到do循环中声明的空列表,还是我还有其他一些问题?顺便说一句,我正在使用clisp.
1.使用正确的格式
在询问Common-Lisp时,请使用正确的格式.例如,请参阅通过Google搜索"常见的lisp格式约定"返回的前三页.
以下是应用于您的函数的传统格式的示例:
;;; Memset - return T if an atom is a top-level member of a set, else NIL
;;; This is needed for the makeset function
(defun memset (atm l)
(cond ((null l) nil)
((eql atm (car l)) t)
(t (memset atm (cdr l)))))
(defun makeset (set1)
(do ((uniq ()))
((null set1) uniq)
(cond ((not (memset (car set1) uniq))
(push (car set1) uniq)))
(setf set1 (cdr set1))))
Run Code Online (Sandbox Code Playgroud)
2.尽可能使用原始函数
你的两个函数在Common-Lisp中都是原始的.
remove-duplicates返回没有重复元素的列表,member检查元素是否属于集合.
3.功能错误
如果你仍想使用你的功能,而不是remove-duplicates,这里有问题.
如果要修改列表,则应使用修改某些内容的函数.这些cons函数构建了一个新对,但不会修改任何东西.因此,在您的表单中(cons (car set1) uniq)添加一个新元素,uniq即您获得一个新列表,其中(car set1)包含第一个元素和unique列表其余部分的元素,但是这个新列表会立即被丢弃,因为它没有分配给任何内容.
您可以通过使用宏setf以uniq这种方式将新值分配给局部变量来更改此值:
(setf uniq (cons (car set1) uniq))
Run Code Online (Sandbox Code Playgroud)
或者您可以通过使用宏来编写等效表单push:
(push (car set1) uniq)
Run Code Online (Sandbox Code Playgroud)
最后,请注意您的cond内部makeset函数可以被更简洁的替换when,从而产生以下功能:
(defun makeset (set1)
(do ((uniq nil))
((null set1) uniq)
(when (not (memset (car set1) uniq))
(push (car set1) uniq))
(setf set1 (cdr set1))))
Run Code Online (Sandbox Code Playgroud)