Это не правда, что dolist
предотвращает от изменения элементов списка. Локальная переменная, которую вы объявляете в dolist
, привязана к последующим элементам списка - действительные элементы, а не их копии. Вы можете делать все, что хотите изменить эти отдельные элементы.
Что вы, скорее всего, путаете, это исходный список - или любой список - который может содержать эти элементы.
Например:
(defun foo (xs)
(dolist (x xs) (setcar x 3)))
(setq bar '((2 2) (4 4 4) (6 6 6)))
(foo bar)
C-h v bar
показывает, что список bar
действительно имел каждый из его элементов изменен dolist
код:
bar's value is
((3 2)
(3 4 4)
(3 6 6))
bar
еще указывает на ячейку же минусы, но для каждого элемента в списке был установлен его номер 3.
UPDATE ответить @duthen:
Это не о «каждый элемент bar
[еще указывает] на тот же минусы ячейки».
Речь идет о модификации списка. Либо вы хотите заменить (или иным образом изменить) фактические элементы в определенном списке, либо нет. Если вы это сделаете, вы можете это сделать, используя dolist
. Элементы не обязательно должны быть conses.
Но если вы хотите просто заменить элементы из определенного списка это означает, что вы не хотите, чтобы изменить список структуры верхнего уровня этого списка. В противном случае вы будете создавать новый список и не изменять только элементы существующего списка.
dolist
сам по себе не изменяет структуру списка верхнего уровня его аргумента списка. Но это никоим образом не мешает вам изменять элементы , которые находятся в этом списке. И это включает в себя изменение структуры их структуры, если они сами являются списками (conses), как в моем примере выше. Сам по себе dolist
не является деревом.
Вот еще один пример, где элементы списка являются строками. Опять же, сами элементы модифицируются - заменены, но список, содержащий их, одинаковый (этот список имеет только структуру списка верхнего уровня).
(defun foo (xs)
(dolist (x xs) (setf (aref x 0) ?$)))
(setq bar '("abc" "def" "ghij"))
(foo bar)
Значение по умолчанию bar
действительно изменено. Его элементы не совпадают - они заменены разными значениями. Сотовые ячейки списка - это те же самые ячейки, но их автомобили не имеют одинаковых значений.
dolist
дает вам доступ только к отдельным элементам из списка. Это не дает вам доступа к требованиям верхнего уровня, которые составляют список. Вы не можете использовать dolist
, чтобы заменить элемент "abc"
на элемент 42
, потому что вы не можете изменить прежний объект, чтобы дать последний. Если вы хотите сделать подобную замену, вам понадобится доступ к conses списка, а не только элементов в списке. Элементами являются только автомобили верхних уровней, которые составляют список.
Задача, заданная вопросом, заключалась в следующем: «обработать элемент, модифицирующий элементы». Это вполне возможно, используя dolist
, как показывают эти примеры. Нет способа изменить "abc"
, чтобы дать вам 42
. Если вам нужна такая замена элемента, вам нужно изменить список.
Если что-то другое подразумевалось под вопросом, тогда это не ясно.
В этом случае, я определенно не нужен первоначальный список больше, и хотел избегайте копирования ... переназначение результатов каркаса в исходный список показало список отходов, но я вижу, что это более читаемо. – user52366