В чем разница между push и add-to-list?

28

Я обнаружил, что различные пакеты в их инструкциях по установке используют push или add-to-list (например, добавление каталога в путь загрузки), и мне было интересно, в чем разница и каков вариант использования для каждого из них.

shadowthief
источник
1
Я изо всех сил пытался преобразовать код, использующий add-to-listв код, используя cl-pushnew, и я нашел это сообщение в блоге весьма поразительным: yoo2080.wordpress.com/2013/09/11/…
dangom

Ответы:

22

То, что упоминает #zck, является одним отличием. Но если бы это было единственным отличием, тогда вы могли бы спросить об cl-pushnewи add-to-list.

Еще одно важное отличие: add-to-listэто функция, которая означает, что она оценивает все свои аргументы, в частности, первый. pushявляется макросом (как есть cl-pushnew) - он не оценивает свой второй аргумент; вместо этого это интерпретирует это как обобщенное место.

Например, если второй аргумент является символом, то он рассматривается как переменная, и значение первого аргумента ограничивается значением этого символа как переменная, и для переменной устанавливаются эти новые минусы.

Как add-to-listсказано в строке документа :

This is handy to add some elements to configuration variables,
but please do not abuse it in Elisp code, where you are usually
better off using `push' or `cl-pushnew'.
Нарисовался
источник
6
Также согласно add-to-list can't use lexical var ...; use push or cl-pushnew
байтовому
(push (5 6) my-list)все равно выдает ошибку - 5это не функция. Чем это отличается от нашего add-to-listповедения?
markasoftware
@markasoftware: что вы пытаетесь сделать? Если вы хотите сдвинуть список (5 6)на место (значение переменной), my-listто вам нужно создать список (5 6). Один из способов сделать это - использовать '(5 6); другой должен использовать (list 5 6). pushоценивает аргумент.
Дрю
@ Теперь вы говорите, что он оценивает аргумент, но ваш ответ буквально гласит: «он не оценивает свой первый аргумент», что является источником моего замешательства.
markasoftware
@markasoftware: извините; У меня была опечатка - я написал «первый аргумент», где я должен был написать «второй аргумент». Исправлено сейчас - спасибо. Второй аргумент push- это место, например, переменная. Первый аргумент вычисляется, ограничивается значением этой переменной, и для переменной устанавливаются эти новые минусы. add-to-listвычисляет свой первый аргумент для получения переменной, значение которой обновляется. pushне оценивает свой второй аргумент, который является переменной для обновления. Порядок arg обратный между двумя.
Дрю
15

Из документации Emacs или C-h f push:

Макрос: push-имя списка элементов

Этот макрос создает новый список, автомобилем которого является элемент, а cdr которого является списком, указанным в listname, и сохраняет этот список в listname.

С той же страницы, или C-h f add-to-list:

Функция: элемент символа добавления в список и необязательное добавление сравнить-fn

Эта функция устанавливает символ переменной, помещая элемент в старое значение, если элемент еще не является членом этого значения.

Так что add-to-listтолько толкает, если элемент еще не там.

zck
источник
cl-pushnewведет себя как add-to-list.
Сам Boosalis
15

Еще одно отличие:

pushдобавляет элемент в начало списка .

add-to-listпозволяет добавить элемент в начало или конец списка .

(setq testasdf nil)

(push 'a testasdf)

testasdf
(a)

(add-to-list 'testasdf 'b)

testasdf
(b a)

;; add element to the end
(add-to-list 'testasdf "hello" t)

testasdf
(b a "hello")
undostres
источник