Lisp中的实例变量?

时间:2011-12-01 05:37:50

标签: lisp clisp

我正在为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)))))))

1 个答案:

答案 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:详细解释

defmethoddefun用于定义(多态)方法的替代方法。但是,如果您不需要多态性,则可以使用(defun my-reverse (l)作为第一行。

labels用于内部函数定义。在这里,它定义了一个名为inner的内部函数,其中包含两个参数listaccinner是执行实际反转的函数,它是一个尾递归函数,因为反转通过尾递归自然而然。 (它可以使用cons构建其结果,因此具有线性复杂性,而您的解决方案需要append,因此具有二次复杂性,因为cons本身是常量,但是{{1}是线性的。)

appendfirst只是restcar的替代名称,cdr主要是endp的替代名称,如果null的参数实际上不是列表,则endp将发出错误信号。

最后,最后一行使用原始列表和空列表作为参数调用inner,并将结果分配给插槽(也称为实例变量)。