バッファローカル変数の挙動

# バッファローカルとは
- Emacs Lispのすべての変数は「バッファローカル」というフラグを持っている
- このフラグはバッファごとに設定されている。たとえば、「変数`x`をバッファ`*scratch*`においてバッファローカルにする」といった操作ができる
- 変数は、何も設定しなければ、どのバッファにおいても、バッファローカルではない

## バッファローカル変数の性質
- 変数には「バッファごとの値」と「デフォルト値」が設定できる
- （現在のバッファにおいて）バッファローカルな変数の読み出し `variable-name` ・セット `(setq variable-name 1)` は、「バッファごとの値」に対して行われる
- （現在のバッファにおいて）バッファローカルでない変数の読み出し・セットは、「デフォルト値」に対して行われる

## `local-variable-p`
変数`x`が（現在のバッファにおいて）バッファローカルかどうかは、
`(local-variable-p 'x)`
で確認できる。

## `make-local-variable`、`kill-local-variable`
変数`x`を現在のバッファにおいてバッファローカルにするには、
`(make-local-variable 'x)`
を評価する。

変数`x`を現在のバッファにおいてバッファローカルでなくするには、
`(kill-local-variable 'x)`
を評価する。

## `default-value`、`setq-default`
`(default-value 'x)`
を評価すると、`x`がバッファローカルであるかどうかに関わらず、`x`のデフォルト値が読み出される。

`(setq-default x 1)`
を評価すると、`x`がバッファローカルであるかどうかに関わらず、`x`のデフォルト値が1にセットされる。

## 例
この例は、新たに作成したバッファ上で評価することを推奨する。また、評価には[lispxmp.el](http://d.hatena.ne.jp/rubikitch/20090313/lispxmp)を用いることを推奨する。

```el
(setq x 'default-value-1)
(make-local-variable 'x)
(setq x 'buffer-local-value)

(local-variable-p 'x)  ; => t
x                      ; => buffer-local-value

(with-temp-buffer  ; 一時バッファ上で評価
  (local-variable-p 'x)      ; => nil
  x                          ; => default-value-1

  (setq x 'default-value-2)
  x                          ; => default-value-2
  )

x                   ; => buffer-local-value
(default-value 'x)  ; => default-value-2

(setq-default x 'default-value-3)
x                   ; => buffer-local-value
(default-value 'x)  ; => default-value-3

(kill-local-variable 'x)
(local-variable-p 'x)  ; => nil
x                      ; => default-value-3
```

# バッファローカルと`let`
Emacs Lispでは、`let`フォームなどによって、ローカルな変数を作ることができる。「バッファローカル」と「ローカル」は全く異なる概念である。

## 例1
この例は、新たに作成したバッファ上で評価することを推奨する。
現在のバッファ名を`Current Buffer`とする。

```el
(setq x 'default-value-1)
(make-local-variable 'x)
(setq x 'buffer-local-value)

(local-variable-p 'x)  ; => t
x                      ; => buffer-local-value

(let ((x 'buffer-local-value-in-let))
  (local-variable-p 'x)  ; => t
  x                      ; => buffer-local-value-in-let

  (with-temp-buffer
    (local-variable-p 'x)  ; => nil
    x                      ; => default-value-1

    (setq x 'default-value-2)
    x                      ; => default-value-2
    )

  x                   ; => buffer-local-value-in-let
  (default-value 'x)  ; => default-value-2
  )

x  ; => buffer-local-value
```

`with-temp-buffer`内での`x`の読み書きは、デフォルト値に対して行われる。したがって、`'buffer-local-value-in-let`を読み出すことはできない。また、`with-temp-buffer`内で`x`の値をセットしても、`x`は`Current Buffer`においてバッファローカルであるため、値は変化しない。ただし、デフォルト値は変更されているので、`(default-value 'x)`によってその値を読み出すことができる。

## 例2
この例は、新たに作成したバッファ上で評価することを推奨する。
現在のバッファ名を`Current Buffer`とする。

```el
(setq x 'default-value-1)
;; バッファ "Another Buffer" を作成し、 "Another Buffer" 上で評価
(with-current-buffer (get-buffer-create "Another Buffer")
  (make-local-variable 'x)
  (setq x 'buffer-local-value-1))

(local-variable-p 'x)  ; => nil
x                      ; => default-value-1

(let ((x 'default-value-in-let))
  (local-variable-p 'x)  ; => nil
  x                      ; => default-value-in-let

  ;; バッファ "Another Buffer" 上で評価
  (with-current-buffer "Another Buffer"
    (local-variable-p 'x)  ; => t
    x                      ; => buffer-local-value-1
    
    (setq x 'buffer-local-value-2)
    x                      ; => buffer-local-value-2
    (default-value 'x)     ; => default-value-in-let

    (setq-default x 'default-value-2))

  x  ; => default-value-2
  )

x  ; => default-value-1
```

`Another Buffer`において`x`はバッファローカルであるため、`x`の読み書きは、バッファごとの値に対して行われる。`Current Buffer`でセットした値は、`(default-value 'x)`によって読み出すことができる。また、`setq-default`によって、`Current Buffer`で読み出される値を設定することができる。

# `make-variable-buffer-local`
`(make-variable-buffer-local 'x)`
を評価すると、`(setq x 1)`などとして`x`に値をセットしたとき、`x`が自動的に（現在のバッファにおいて）バッファローカルになる。この、自動的にバッファローカルにする効果は、すべてのバッファにおいて有効になる。

## 例1
この例は、Emacsを再起動してから評価することを推奨する。

```el
(setq x1 'default-value)
(make-variable-buffer-local 'x1)

(local-variable-p 'x1)  ; => nil
x1                      ; => default-value

(setq x1 'buffer-local-value)
(local-variable-p 'x1)  ; => t
x1                      ; => buffer-local-value
```

`(make-variable-buffer-local 'x1)`を評価した後に、`x1`の値をセットすると、`x1`が自動的にバッファローカルになっている。

## 例2
この例は、Emacsを再起動してから評価することを推奨する。

```el
(setq x2 'default-value)
(make-variable-buffer-local 'x2)

(with-temp-buffer
  (local-variable-p 'x2)  ; => nil
  x2                      ; => default-value

  (setq x2 'buffer-local-value)
  (local-variable-p 'x2)  ; => t
  x2                      ; => buffer-local-value
  )

(local-variable-p 'x2)  ; => nil
x2                      ; => default-value
```

`(make-variable-buffer-local 'x2)`を評価したバッファとは、異なるバッファの上で`x2`に値をセットしても、`x2`は（移ったバッファにおいて）バッファローカルになる。

## `let`によるシャドウイング
`(make-variable-buffer-local 'x)`を評価したのち、`let`などで`x`をシャドウした上で値をセットしても、`x`はバッファローカルにならない。

## 例3
この例は、Emacsを再起動してから評価することを推奨する。

```el
(setq x3 'default-value)
(make-variable-buffer-local 'x3)

(let ((x3 'default-value-in-let-1))
  (local-variable-p 'x3)  ; => nil
  x3                      ; => default-value-in-let-1

  (setq x3 'default-value-in-let-2)
  (local-variable-p 'x3)  ; => nil
  x3                      ; => default-value-in-let-2
  )
```

`(make-variable-buffer-local 'x3)`を評価したあとで、`let`によって`x3`に値をセットしているが、`x3`はバッファローカルにならない。また、シャドウした後の`x3`に値をセットしても、`x3`はバッファローカルにならない。

## 例4
この例は、Emacsを再起動してから評価することを推奨する。

```el
(let ((x4 'default-value-in-let))
  (make-variable-buffer-local 'x4)
  (setq x4 'buffer-local-value))

(local-variable-p 'x4)  ; => t
x4                      ; => buffer-local-value
```

ローカルな変数に`make-variable-buffer-local`を適用しても、変数をシャドウせずにセットすれば、バッファローカルになる。ただし、これは邪悪なコードらしく、評価すると

> Making x4 buffer-local while let-bound!

という警告がエコーエリアに表示される。

* * *

注意すべきは、
`(make-variable-buffer-local 'x)`
を評価した時点では、`x`はバッファローカルにならないことである。make-variable-buffer-local（変数をバッファローカルにする）という名前は、この点で誤解しやすい。そのため、筆者はinit.elで
`(defalias 'make-variable-autolocal 'make-variable-buffer-local)`
と設定している。