LINUX.ORG.RU

lisp: list + nth + set = ?


0

0

Имеется следующий код:

(defvar a nil)
(defvar b nil)

(setq a '((0 0 0)
(0 0 0)
(0 0 0)))

(setq b '((1 0 0)
(2 0 0)
(3 0 0)))

(defun out (x)
(dolist (i x)
(format t "~a~%" i))
(format t "~%"))

(out a)
(out b)
(setf (nth 1 (nth 1 a)) 1)
(setf (nth 1 (nth 1 b)) 1)
(out a)
(out b)

Выводит следующее:

(0 0 0)
(0 0 0)
(0 0 0)

(1 0 0)
(2 0 0)
(3 0 0)

(0 1 0)
(0 1 0)
(0 1 0)

(1 0 0)
(2 1 0)
(3 0 0)

Почему setf работает так странно? sbcl 1.0.6.40

★★★★★

Видимо, компилятор соптимизировал (setq a '((0 0 0) (0 0 0) (0 0 0))) таким образом, что все три элемента списка указывают на один экземпляр '(0 0 0).

(setq a (list (list 0 0 0) (list 0 0 0) (list 0 0 0))) работает как ожидалось.

watashiwa_daredeska ★★★★
()

CL-USER> (out a)
(out b)
(0 0 0)
(0 1 0)
(0 0 0)

(1 0 0)
(2 1 0)
(3 0 0)

CL-USER> (lisp-implementation-type)
"SBCL"
CL-USER> (lisp-implementation-version)
"1.0.6"

stassats ★★★★
()
Ответ на: комментарий от watashiwa_daredeska

Насколько я понимаю, sbcl пытается делать lazy evaluation, и у него copy-on-write, типа, глючит? Lisp разве ленивый язык?

mv ★★★★★
() автор топика
Ответ на: комментарий от mv

sbcl — да

На будущее стоить помнить что lisp'ов много, у каждого интерпретатора (компилятора) свой :)

catap ★★★★★
()

Да, очень похоже на баг. Напиши в sbcl-devel

yyk ★★★★★
()

Кому интересно, в sbcl-devel ответили:

clhs:quote says:

> The consequences are undefined if literal objects (including quoted > objects) are destructively modified.

So this behavior is allowed by the spec. Don't use a quoted literal if you want to modify a and b.

С (list (list ... всё работает.

mv ★★★★★
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.