我正在为CLOS类编写一个函数来反转所述类的对象的列表元素。
我有一个方法会返回反向列表,但是如何将对象列表设置为该列表呢?我可以在存储列表的函数中有一个实例变量,然后将元素设置为该变量吗?或者有更简单的方法吗?
以下是现在的方法:
(defun my-reverse (lst)
(cond ((null lst) ‘())
(t (append (my-reverse (cdr lst)) (car lst)))))
传递的对象是(l my-list),然后访问者是(my-list-ls l)。
编辑:意识到cons
在2个列表中不起作用。
Edit2:我认为正确的代码是:
(defun my-reverse (l my-list)
(cond ((null (my-list-ls l) ‘())
(t (setf (my-list-ls l) (append (my-reverse (cdr (my-list-ls l)))
(car (my-list-ls l)))))))
答案 0 :(得分:1)
如果要修改对象的插槽,则需要将该对象本身传递给您的函数,而不仅仅是要更改的插槽的值。
编辑:关于问题的编辑2
我假设my-list
是该类的名称,并且您实际上并不想将其传递给该函数,对吧?在这种情况下,您应该使用defun
替换defmethod
。此外,在颠倒整个列表后,最好只更改一次实例,而不是每一步。您可以使用内部函数:
(defmethod my-reverse ((l my-list))
(labels ((inner (list acc)
(if (endp list)
acc
(inner (rest list) (cons (first list) acc)))))
(setf (my-list-ls l) (inner (my-list-ls l) ()))))
编辑2:详细解释
defmethod
是defun
用于定义(多态)方法的替代方法。但是,如果您不需要多态性,则可以使用(defun my-reverse (l)
作为第一行。
labels
用于内部函数定义。在这里,它定义了一个名为inner
的内部函数,其中包含两个参数list
和acc
。 inner
是执行实际反转的函数,它是一个尾递归函数,因为反转通过尾递归自然而然。 (它可以使用cons
构建其结果,因此具有线性复杂性,而您的解决方案需要append
,因此具有二次复杂性,因为cons
本身是常量,但是{{1}是线性的。)
append
和first
只是rest
和car
的替代名称,cdr
主要是endp
的替代名称,如果null
的参数实际上不是列表,则endp
将发出错误信号。
最后,最后一行使用原始列表和空列表作为参数调用inner
,并将结果分配给插槽(也称为实例变量)。