22

What is the difference between setq and defvar in Emacs lisp?

I see common lisp version of the same question at https://stackoverflow.com/questions/3855862. Are they same in Elisp?

Yasushi Shoji
  • 2,151
  • 15
  • 35

1 Answers1

29

You should ask Emacs this question: C-h i, choose the Elisp manual (m Elisp), and search the index for "defvar" (i defvar). That takes you to node Defining Variables.

Emacs tells you that defvar allows attaching a doc string, and that if the variable already has a value then it does nothing.

It also tells you about the use of defvar with no value to be assigned: (defvar foo). It tells you that that declares the variable to be dynamically scoped.

setq has none of those properties.

defvar and setq are similar, but not quite the same, in Emacs Lisp and Common Lisp.

Read more, to learn more.

UTF-8
  • 885
  • 6
  • 22
Drew
  • 75,699
  • 9
  • 109
  • 225
  • 3
    In fact defvar also declares "dynamical scoping" if there is a value given, and that remains true even if the variable already had a value. OTOH "if the variable already has a value then it does nothing" is true for all valid uses of defvar (and the bytecompiler should issue a warning in the remaining cases, i.e. if declaring a variable after its first use). – YoungFrog Dec 31 '16 at 18:17
  • so it sounds like `defvar` is a global variable (as in imperative programming style) and a convention for customization, while setq is more like a let binding in functional programming languages (with dynamic/lexical scoping rule depending of which global scoping mode is active.........) – nicolas Dec 01 '18 at 11:04
  • @nicolas: Please read the manual. `setq` sets a var value, regardless of whether the var (occurrence) is local. `defvar` declares a var as global. (It may also be "buffer-local": `local-variable-p`.) A var occurrence bound as a function arg or by `let` is "local" in the usual sense. If a var bound by `let` etc. is global (or buffer-local) then a local binding (usual sense) is created for it, for the duration/scope of that `let`. Within that binding scope, `setq` changes the local value. It's better to talk about a var *occurrence* being local (on stack) or global (on heap) than a var being so. – Drew Dec 01 '18 at 18:22
  • @drew I did. I confess I dont quite understand everything, apart from `defvar` being a global variable. It looks absolutely mad to have a 2 page explanation for binding, but your help is precious for navigating the manual, so thank you – nicolas Dec 01 '18 at 18:57
  • 1
    @nicolas: Take your time reading it and rereading it. Sometimes what it says is precise but hard to grasp, like a formal specification. Once you get it, it could be helpful for you to `M-x report-emacs-bug` to suggest improvements that might help others get it easier. – Drew Dec 01 '18 at 20:21
  • 1
    @nicolas: Start with understanding a variable on *the heap* (aka a global or buffer-local variable). You likely already understand true local variables, that is, variables on *the stack*. Googling might also help. – Drew Dec 01 '18 at 20:23
  • @Drew thanks for your tips and for the context you provide in your answer – nicolas Dec 02 '18 at 11:44
  • @nicolas If you're at all familiar with other languages, one of the distinctions here is between variable *definition* (`int foo;`) and variable *assignment* (`foo = 42`). `setq` is assignment, and it doesn't care about the scope/lifetime of what it's assigning to (`foo = 42;` doesn't care if `foo` is global, local, or whatever). `defvar` is definition, which of course can optionally contain assignment of an initial value (`int foo = 42;`). – mtraceur Apr 29 '23 at 03:49