make-local-variable vs make-variable-buffer-local
Tags: emacs, lisp
Published: 2019-01-10 12:23:53

---
title: make-local-variable vs make-variable-buffer-local
published: true
tags: ["emacs", "lisp"]
---

These two function names are confusing, but they are different functions.

The content of this article is explained in [Creating Buffer-Local](https://www.gnu.org/software/emacs/manual/html_node/elisp/Creating-Buffer_002dLocal.html) in **GNU Emacs Lisp Reference Manual**.

## TL;DR

* “**Local**” in Emacs means that variables can hold independent values for each buffer.
* `make-local-variable` *\*temporarily\** makes the variable local in the current buffer
* `make-variable-buffer-local` ensures that the variable is *\*always\** set as local.

Emacs Lispers targeting **Emacs 24.3** and later should only use `defvar-local` and` setq-local`.  Looking at [its implementation (`subr.el` added in Emacs 24.3)](https://github.com/emacs-mirror/emacs/blob/emacs-26.0.91/lisp/subr.el#L120-L133), you will find a difference between the two functions.

```emacs-lisp
(defmacro setq-local (var val)
  "Set variable VAR to value VAL in current buffer."
  ;; Can't use backquote here, it's too early in the bootstrap.
  (declare (debug (symbolp form)))
  (list 'set (list 'make-local-variable (list 'quote var)) val))

(defmacro defvar-local (var val &optional docstring)
  "Define VAR as a buffer-local variable with default value VAL.
Like `defvar' but additionally marks the variable as being automatically
buffer-local wherever it is set."
  (declare (debug defvar) (doc-string 3))
  ;; Can't use backquote here, it's too early in the bootstrap.
  (list 'progn (list 'defvar var val docstring)
        (list 'make-variable-buffer-local (list 'quote var))))
```

## `make-local-variable`

In the past, I wrote as follows in my `init.el`:

```emacs-lisp
(defun my/enh-ruby-mode-hook ()
  "Enhanced Ruby Modeでだけ ac-ignore-case を t にしたいお"
  (set (make-local-variable 'ac-ignore-case) t))
```

`setq-local` makes that code simple.

```emacs-lisp
(defun my/enh-ruby-mode-hook ()
  "Enhanced Ruby Modeでだけ ac-ignore-case を t にしたいお"
  (setq-local ac-ignore-case t))
```

If you are the author of Lisp packages, please carefully consider using this function.  Do you want to set it *temporarily* locally?

## `make-variable-buffer-local`

This is exclusively a function for Lisp package authors.

```emacs-lisp
;;;###autoload
(progn
  (defvar copy-file-on-save-dest-dir nil
    "Path to deployment directory or convert (mapping) function.")
  (make-variable-buffer-local 'copy-file-on-save-dest-dir)
  (put 'copy-file-on-save-dest-dir 'safe-local-variable #'stringp))
```

This function reduces repetition of function names.

```emacs-lisp
;;;###autoload
(progn
  (defvar-local copy-file-on-save-dest-dir nil
    "Path to deployment directory or convert (mapping) function.")
  (put 'copy-file-on-save-dest-dir 'safe-local-variable #'stringp))
```

It is not necessary to use `setq-local` for variables defined in this way. Please use `setq` with confidence.

Do not forget the definition of `safe-local-variable` when you provide variables that you can customize for per directory/project. [Directory Variables](https://www.gnu.org/software/emacs/manual/html_node/emacs/Directory-Variables.html) a better idea than `defcustom` + `setq-local`.


...It is the worst that the notation `safe-local-variable` and [`defcustom :type`](https://www.gnu.org/software/emacs/manual/html_node/elisp/Customization-Types.html) is different.

## Afterword

Replacing the *strange twins* with `defvar-local` and` setq-local` means dropping support for versions below **Emacs 24.2**.

**Emacs 24.3** was released on March 10, 2013, but [I ceased to pay for *the rotten milks*](https://github.com/emacs-php/php-mode/pull/467).