Проблема с доступом к слотам в Лиспе (CLOS) - PullRequest
1 голос
/ 26 сентября 2010

У меня есть класс Node, в котором есть слот 'element', который содержит список с числами и одной буквой, например:

'(1 2 3 b 4 5 6)

<code>
(defclass node ()
  ((element :reader get-element
            :writer set-element
            :initform '()
            :initarg :element
            :documentation "The element"))

Часть программы должна занять слот 'element', поменять букву одним из чисел и, наконец, создать новый объект Node с поменявшимся списком в качестве слота 'element'. У меня уже есть функция подкачки, которая получает список и двух членов этого списка, и с помощью функции rotatef они меняются местами.

Чтобы проверить, что функция подкачки работает, я создал следующий фрагмент кода, который сохраняет во временной переменной элемент и заменяет букву 'b' на число в списке:

<code>
(setf root (make-instance 'node))
(set-element '(1 2 3 b 4 5 6 7 8) root)</p>

<p>(setf temp (get-element root))
(swap temp 'b 4)

Проблема в том, что слот 'element' корневого объекта заменяется на временный. Странно, я пытался изменить функцию подкачки, чтобы изменить, и она не изменяет ни одну из двух.

Я не знаю, есть ли способ присвоения слота переменной или способ предотвращения вышеуказанного.

Спасибо.

Ответы [ 2 ]

3 голосов
/ 26 сентября 2010

Некоторые другие замечания:

  • вместо метода получения и установки используйте метод доступа. Это обычно предпочтительнее.

  • списки создаются с помощью таких функций, как LIST или COPY-LIST. Список, написанный как '(1 b 2), является в исходном коде буквальной константой и не должен изменяться. В стандарте CL не определено, что произойдет, если вы попытаетесь изменить список литералов. Это может иметь нежелательные последствия. Если у вас есть список литералов, и вы хотите изменить его, вы должны сначала скопировать его с помощью COPY-LIST (или COPY-TREE) и изменить эту копию.

  • вам также необходимо изучить разницу между неразрушающими операциями, такими как REVERSE, и, возможно, разрушительными операциями, такими как NREVERSE. Если вы хотите, чтобы исходный список был неизменным, используйте неразрушающие операции. Характер операций со списком или последовательностью описан в гиперпецификации Common Lisp для каждой операции.

2 голосов
/ 26 сентября 2010

Reverse создает и возвращает новый список.Rotatef (так же, как setf, incf и т.п.) изменяют место.Вам нужно будет copy-list или copy-tree ваш element, чтобы создать новый список, который вы затем измените.

...