2016-03-24 2 views
1

Я новичок в elisp и все еще изучаю, как вещи, которые я должен писать на C или Perl, перевести на соответствующий код elisp. В конкретном случае мне нужно обработать элемент списка, модифицирующий их. Я считал dolist, но в отличие от, например, Perl's foreach Я не могу изменить исходные значения списка. Я придумал следующий код, но он кажется слишком сложным (по крайней мере, это не выглядит очень читаемым для меня):Элементы изменения списка процессов в elisp

(setq x '("a" "b" "c")) 
(let ((p x)) 
    (while (car p) 
    (setcar p (concat ">" (car p))) 
    (setq p (cdr p)))) 

Есть ли лучше способ добиться того же?

ответ

1

Ммм ... Как я французский, я не уверен, что могу четко объяснить, что я имею в виду ...

«изменить исходные значения списка» неоднозначен, как «изменение элементов списка» ,

Дрю, в вашем примере, вы показываете, что, с dolist, вы можете перечислить список, и для каждого элемента в списке, вы можете применить функцию (например, setcar), которая изменит что-то внутри этот пункт.

Хорошо.

Но, с dolist, вы не можете заменить каждый элемент списка другим товаром, например, заменять p на (concat ">" p).

В вашем примере (2 2) является eq(3 2).

Итак, вы можете сказать, что bar все еще указывает на одну и ту же ячейку cons и что каждый элемент bar также по-прежнему указывает на одну и ту же ячейку cons.

Мы можем сказать, что вы изменили/модифицировали первый элемент (на французском языке, «Vous Avez CHANGE ле премьеры ЭЛЕМЕНТА»), но вы не можете сказать, что вы заменили первый пункт ("уоиз Avez Changé де премьеры элемент").

Aamof, смешно, что на французском языке есть только одна другая буква!

Во всяком случае, вы не можете сделать это с dolist, но вы можете сделать это с do:

(do ((p x (cdr p))) ((null p) x) (setcar p (concat ">" (car p))))

1

Я бы порекомендовал вас, чтобы попытаться подумать о том, как сделать то, что вы хотите без, изменяя список. То есть вместо этого возвращает другой список. Например:

(let ((newlist 
     (mapcar (lambda (p) (concat ">" p)) 
       x))) 
    ...use newlist...) 
+0

В этом случае, я определенно не нужен первоначальный список больше, и хотел избегайте копирования ... переназначение результатов каркаса в исходный список показало список отходов, но я вижу, что это более читаемо. – user52366

1

Это не правда, что 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. Если вам нужна такая замена элемента, вам нужно изменить список.

Если что-то другое подразумевалось под вопросом, тогда это не ясно.

+0

--- удален --- – user52366

Смежные вопросы