DELETE
работает, изменяя CDR
предыдущей cons-ячейки списка так, чтобы она указывала на ячейку, расположенную после удаляемых элементов. Но если вы удаляете первый элемент списка, предыдущая ячейка cons для изменения отсутствует.
Хотя эта реализация на самом деле не указана в стандарте языка, так работает практически каждая реализация.
Поскольку при удалении первого элемента списка нет предыдущей ячейки cons, которую нужно изменить, он просто возвращает вторую ячейку cons. Таким образом, несмотря на то, что DELETE
разрешено изменять список, вы все равно должны присвоить результат своей переменной, чтобы обработать этот случай. Кроме того, следует подчеркнуть, что деструктивное поведение только разрешено по стандарту, а не требуется. Таким образом, существует отдаленная вероятность того, что какая-то реализация вообще не реализует его деструктивно, и вы также должны допустить это.
И даже если DELETE
сработало, изменив CAR вместо CDR, все же есть случай, когда он не может сделать деструктивно: удаление всех элементов списка, например.
(setq *test* (list 'a 'a))
(delete 'a *test*)
Это приводит к пустому списку, т.е. NIL
. Но *test*
по-прежнему содержит ячейку cons, которая была головой исходного списка, и DELETE
никак не может это изменить. Итак, вы должны сделать:
(setq *test* (delete 'a *test*))
чтобы установить *test*
на NIL
.
person
Barmar
schedule
12.10.2013