112

I have a question about Emacs Lisp. What is the difference between setq and setq-default?

Tutorials say setq takes effect in the local buffer while setq-default affects all buffers.

For example, if I wrote (setq a-var a-vars-value) in init.el, I found after starting Emacs and opening a new buffer, the a-var is also there and its value is a-vars-value. I thought it was not supposed to be there. It seems there is no difference between setq and setq-default.

Is there something wrong with my understanding?

For example:

  1. I wrote (setq hello 123) in the init.el file, and I run emacs abuffer in the shell, then I input "hello C-x C-e", it shows "123". The same happens when I run this in all new buffers.

  2. I wrote (setq tab-width 4) in the init.el file. When I run tab-width C-x C-e, it shows "8" (Current mode is 'Text'). However, when I use (setq-default tab-width 4), it show "4". I can't explain this phenomenon.

ROMANIA_engineer
  • 54,432
  • 29
  • 203
  • 199
ruanhao
  • 4,663
  • 6
  • 28
  • 43

1 Answers1

128

Some variables in Emacs are "buffer-local", meaning that each buffer is allowed to have a separate value for that variable that overrides the global default. tab-width is a good example of a buffer-local variable.

If a variable is buffer-local, then setq sets its local value in the current buffer and setq-default sets the global default value.

If a variable is not buffer-local, then setq and setq-default do the same thing.

In your case 2, (setq tab-width 4) set the buffer-local value of tab-width to 4 in the current buffer, leaving the global default value of tab-width still at 8, so when you evaluated tab-width in a different buffer that had no local value, you saw that 8. Then, when you set the default value to 4, that buffer picked it up, since it still had no local value.

dfan
  • 5,714
  • 1
  • 31
  • 27
  • when I (sets tab-width 4), and evaluate it, it is always 8 in every buffer. I don't know why. Seems it does not take effect. But when I use (sets-default tab-width 4), it takes effect in every buffer. I also do not know why:( – ruanhao Aug 11 '13 at 16:11
  • `(setq tab-width 4)` takes effect in the buffer where you evaluated the expression; if you evaluate it in the `*scratch*` buffer then examine its value in that buffer. – tripleee Aug 11 '13 at 16:13
  • 1
    `tab-width` is a buffer-local variable. So when you `(setq tab-width 4)`, it is only set to 4 in the current buffer. All other buffers retain a `tab-width` of the global default, 8. When you `(setq-default tab-width 4)`, you are changing the global default of `tab-width` to 4, so now every buffer that has not defined `tab-width` itself has that new default. – dfan Aug 11 '13 at 16:14
  • I add (setq tab-width 4) in init.el, and I run "emacs hello" to open buffer hello. Is there possibility that the sentence in init.el does not take effect on buffer 'hello' in this way? – ruanhao Aug 11 '13 at 16:19
  • 4
    Yes. See the list of emacs' [Sequence of Actions at Startup](http://www.gnu.org/software/emacs/manual/html_node/elisp/Startup-Summary.html). Reading the init file is step 12, and bringing up the initial buffer is step 23. – dfan Aug 11 '13 at 16:35
  • 1
    ah, enlightened. So when i (setq tab-width 4), no buffer is initialized and there is no specific buffer that corresponds to '(setq tab-width 4)'. In this case, this config in 'init.el' is somewhat useless, am i right? – ruanhao Aug 12 '13 at 00:50
  • 3
    @ruanhao If you (setq tab-width 4) in the init.el, then it will only apply to that buffer (init.el). If you want this change to apply to all new buffers, then (setq-default tab-width 4) will accomplish this. Additionally, if you want to create a mode for a specific type of file, you would probably want to use (setq tab-width 4) so as not to override the global default. – Hemm Jan 14 '14 at 18:16
  • How can you tell if a variable is buffer-local or not? – Didier A. Jan 13 '23 at 21:56
  • The easiest way as a user is to type `C-h v tab-width` (say) and look at the documentation for it. – dfan Jan 14 '23 at 16:25