SBCL 1.3.1# 'равное сравнение true по сравнению с (список 7 1), но false по сравнению с' (7 1), почему?
В общем, a
является список, '(7)
, b
устанавливается в тот же список с помощью setq
. Значение добавляется к b
. Список c
установлен на ожидаемый результат после добавления, то есть '(7 1)
. a
затем сравнивается с c
и правильно сравнивает значение true. Однако, когда a
сравнивается через (equal a '(7 1))
, он сравнивает значение false.
Я предполагаю, что компилятор не видел приложение, как это было сделано на b
, и оптимизировал сравнение с константой с неправильным результатом. Если да, то какие варианты есть, чтобы опрокинуть компилятор. Может ли a
быть отмечен как специальный как-то? Или, кроме вопросов стиля, связанных с деструктивным программированием, есть ли что-то еще здесь?
(defun test-0()
(let ((a '(7))
b
(c '(7 1)))
(setq b a)
(setf (cdr b) (cons 1 '()))
(pprint (list a b c))
(values (equal c a) (equal '(7 1) a) (equal (list 7 1) a) c a)))
* (test-0)
((7 1) (7 1) (7 1))
T
NIL <== ??
T
(7 1)
(7 1)
Настоящий транскрипт загружается и запускается в пустой среде. Файл является копией и вставкой кода выше. Можно видеть, что сообщений об ошибках нет. Здесь интересно видеть, что результаты разные.
§sbcl> sbcl
This is SBCL 1.3.1.debian, an implementation of ANSI Common Lisp.
More information about SBCL is available at <http://www.sbcl.org/>.
SBCL is free software, provided as is, with absolutely no warranty.
It is mostly in the public domain; some portions are provided under
BSD-style licenses. See the CREDITS and COPYING files in the
distribution for more information.
* (load "src/test-0")
T
* (test-0)
((7 1) (7 1) (7 1))
NIL
NIL
T
(7 1)
(7 1)
*
Вы должны избегать использования цитируемых списков при привязке значений к переменной. Они всегда склонны вызывать странное поведение при изменении (просто замените их на '(list ...)', и код должен работать). – jkiiski
Да, это исправляет его, и имеет смысл, что цитируемые списки будут постоянными и недоступны для модификации. Если вы хотите, чтобы это как «ответ», добавьте его, и я отметю его. –
@ user244488 Это подходящий ответ для «что мне делать, чтобы этого избежать», но это не объясняет поведение, которое вы получаете. Модификация * does * происходит, фактически (хотя это неопределенное поведение); поведение заключается в том, что тест на равенство оптимизируется. Я добавил ответ с некоторыми подробностями. –