Значение по умолчанию для ключевого аргумента :test
в REMOVE
(и, в более общем случае, функции, принимающие параметр тестовой функции): EQL
.
Когда вы пишете (remove '(1 2 3) '((1 2 3) (4 5 6)))
, вы не гарантируете, что оба списка, которые печатаются как (1 2 3)
, идентичны .Скорее всего, они представлены разными cons-ячейками:
(eql '(1 2 3) '(1 2 3))
=> NIL
Компилятор может обнаружить, что оба списка равны во время компиляции и использовать одну и ту же базовую память, что делает их EQ, но вы, как правило, не можете предположить, что этослучай.
Если, однако, вы дважды использовали один и тот же список, REMOVE
будет работать так, как вы ожидаете:
(let ((a '(1 2 3))) (remove a (list a '(4 5 6))))
=> ((4 5 6))
Вышеприведенный пример также может быть записан следующим образом с переменными чтения (результат аналогичен, но весь список заключен в кавычки, вместо этого он создается во время выполнения с list
):
(remove '#1=(1 2 3) '(#1# (4 5 6)))
=> ((4 5 6))
В общем случае, когда вы не манипулируете объектами по их идентификаторам, вам нужноиспользуйте тестовую функцию, которая знает, как сравнивать списки, чтобы различные списки с одинаковым содержимым считались равными:
(remove '(1 2 3) '((1 2 3) (4 5 6)) :test #'equal)
=> ((4 5 6))
При использовании приведенного выше кода элементы сравниваются с EQUAL
.