In some cases you can use either function to add an element to a list. That you can do that does not mean that you should, however.
The recommendation by Emacs is to use only
add-hook for a hook. And
cl-pushnew) is generally recommended in place of
add-to-list. (Common Lisp does not even have something like
Note that, unlike
pushnew does not require its second argument to evaluate to a symbol (variable) -- it is a very general macro. But it is a macro, not a function, so you cannot map it (e.g.
funcall it, etc.
add-to-list can typically be replaced by macro
pushnew. The first
add-to-list arg is a symbol that is used as a list-valued variable. Its second is any Lisp value. Its fourth,
COMPARE-FN is a function that tests whether the element to add is already present - it has no counterpart in
add-hook, which always tests using
add-hook arg, the hook variable, need not have a list as its value -- it can be a single function. The second arg should be a function, but there is no check that it is. (That answers your second question.) And its fourth arg,
LOCAL, means update the buffer-local, not the global, value of the hook - it has no counterpart in
What you mention about their difference, that
add-hook binds an unbound symbol, is true. That's important for a hook, in particular, because most hook variables are not created by default. They are implicit in the definition of a mode, and they are created on the fly only when they are actually needed.
Is that bind-if-not-bound behavior what you really want for every add-something-to-a-list use case? I'm guessing probably not. But if that's important to you for some reason then you can easily add such behavior to your own function that adds an element to a variable that should be list-valued.
C-h f for other differences, or (better) check their definitions in
If you understand the differences then you can of course use each any way you like, taking its behavior into account. But for readability by others (or by you, later on), even in contexts where the behavior differences might not matter, it generally makes sense to use them as they were intended.
By using them in the intended/expected way, you do not mislead readers of your code. The principal reason for using each as it is intended is to signal the intention/use to others and to yourself later.
I differ from SDS's fine answer in this respect:
add-to-list is not just for "other global customization variables". It has nothing particularly to do with customization variables or with
It is not the case that
add-to-list are only for your
.emacs and that
pushnew is only for Lisp code. For one thing,
.emacs contains Lisp code. ;-)
It is perfectly fine, and common, for Lisp code to use
pushnew is more common than
add-to-list nowadays). (For decades Emacs did not even have
add-to-list was then recommended for all non-hook lists.)
And it is perfectly fine for your
.emacs file to use
The simple rule to remember is just this:
add-hook only with hook variables, and
pushnew only to add an element to a (non-hook) list value.
If you really need or want something different, it is pretty easy to define it, and a good place to start is to look at the existing code for
add-hook and either