I've found that different packages in their installation instructions use either push or add-to-list (For example adding a directory to load-path) and I was wondering what the difference is and what the use case for each would be.
3 Answers
What #zck mentions is one difference. But if that were the only difference then you could ask about cl-pushnew
and add-to-list
.
Another important difference: add-to-list
is a function, which means that it evaluates all of its arguments, in particular, the first one. push
is a macro (as is cl-pushnew
) - it does not evaluate its second argument; instead, it interprets it as a generalized place.
For example, if the second argument is a symbol then it is regarded as a variable, and the value of the first argument is consed onto the value of that symbol as a variable, and the variable is set to that new cons.
As the doc string of add-to-list
says:
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'.
-
7Also according to the byte-compiler:
add-to-list can't use lexical var ...; use push or cl-pushnew
Commented Jan 15, 2015 at 12:05 -
(push (5 6) my-list)
still gives me an error --5
is not a function. How is this different thanadd-to-list
's behavior? Commented May 19, 2019 at 17:46 -
@markasoftware: What are you trying to do? If you want to push the list
(5 6)
to the place (value of variable)my-list
then you need to create the list(5 6)
. One way to do that is to use'(5 6)
; another is to use(list 5 6)
.push
evaluates the argument.– DrewCommented May 19, 2019 at 19:56 -
@Drew you say now that it evaluates the argument, but your answer literally states "it does not evaluate its first argument", which is the source of my confusion. Commented May 20, 2019 at 2:00
-
@markasoftware: I'm sorry; I had a typo - I wrote "first argument" where I should have written "second argument". Corrected now - thanks. The second arg to
push
is a place, such as a variable. The first arg is evaluated, consed onto the value of that variable, and the variable is set to that new cons.add-to-list
evaluates its first arg to produce the variable whose value gets updated.push
does not evaluate its second arg, which is the variable to update. The arg order is reversed between the two.– DrewCommented May 20, 2019 at 2:46
Another difference:
push
adds element to the beginning of list.
add-to-list
allows you to add element to either the beginning or end of 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")
From the Emacs documentation, or C-h f push
:
Macro: push element listname
This macro creates a new list whose car is element and whose cdr is the list specified by listname, and saves that list in listname.
From the same page, or C-h f add-to-list
:
Function: add-to-list symbol element &optional append compare-fn
This function sets the variable symbol by consing element onto the old value, if element is not already a member of that value.
So add-to-list
only pushes if the element isn't already there.
add-to-list
to code usingcl-pushnew
, and I found this blog post to be quite enlightling: yoo2080.wordpress.com/2013/09/11/…