既存関数内で使われている変数を外部から上書きする

関数内で使われている変数を一時的に変えたい場合があると思います。
バッドノウハウかもしれませんが、個人用の設定にはとても有用です。

## Dynamic scope

```el
(setq foo 1)

(defun bar1 () foo)

(let ((foo 2))
  foo                        ; => 2
  (bar1)                     ; => 2
  )

foo                          ; => 1
(bar1)                       ; => 1
```

一時的に関数`bar`内の変数`foo`がグローバル変数`foo`ではなく、`let`で定義した`foo`を見るようになりました。
しかし、これはダイナミックスコープ時のみ有効ですので、レキシカルスコープの場合には以下のようになってしまいます。

## Lexical scope

```el
;;; -*- lexical-binding: t -*-

(setq foo 1)

(defun bar1 () foo)

(let ((foo 2))
  foo                        ; => 2
  (bar1)                     ; => 1
  )

foo                          ; => 1
(bar1)                       ; => 1
```

レキシカルスコープでは関数`bar1`内の変数`foo`はグローバル変数`foo`を見ています。
(1行目に特殊コメントを書いておくとレキシカルスコープになります。)

## Override Inner variables safely

```el
;;; -*- lexical-binding: t -*-

(setq foo 1)

(defun bar1 () foo)

(let ((_foo foo))
  (unwind-protect
      (progn
        (setq foo 2)
        foo                   ; => 2
        (bar1)                ; => 2
        )
    (setq foo _foo))
  )

foo                           ; => 1
(bar1)                        ; => 1
```

上記の方法ならダイナミック/レキシカル両方のスコープでセーフですね。
一時的にグローバル変数`foo`の値を変更して、最後に`unwind-protect`によって確実に元の値に戻しています。

## Macro

```el
;;; -*- coding: utf-8; lexical-binding: t -*-

(require 'cl-lib)
(defmacro overriding-let (bindings &rest body)
  (declare (indent 1))
  (let (original-pairs
        local-pairs
        overriding-targets
        (bin `,bindings))
    (cl-dotimes (x (length bin))
      (let ((b (nth x bin))
            s v)
        (cl-typecase b
          (cons (setq s (or (ignore-errors (car b)) b))
                (if (boundp s)
                    (progn
                      (setq v (symbol-value s))
                      (setq original-pairs (cons (cons s v) original-pairs))
                      (setq overriding-targets (cons b overriding-targets)))
                  (setq local-pairs (cons b local-pairs))))
          (symbol
           (setq local-pairs (cons b local-pairs)))
          (t (error "Binding format error")))))

    `(let ,local-pairs
       (unwind-protect
           (progn
             (mapc (lambda (x)
                     (let ((s (intern (symbol-name (car x))))
                           (v (car (cdr x))))
                       (set s v)))
                   ',overriding-targets)
             ,@body)
         (mapc (lambda (x)
                 (let ((s (car x))
                       (v (cdr x)))
                   (set s v)))
               ',original-pairs)))))


(setq foo1 1)
(setq foo2 9)

(defun bar1 () foo1)
(defun bar2 () foo2)

(overriding-let ((foo1 2)
                 (foo2 99)
                 (foo3 30)  ;; グローバル変数ではないのでローカル変数として扱う
                 foo4)      ;; グローバル変数ではないのでローカル変数として扱う (宣言のみ)
  (bar1)                       ; => 2
  (bar2)                       ; => 99
  foo1                         ; => 2
  foo2                         ; => 99
  foo3                         ; => 30
  foo4                         ; => nil
  )

(bar1)                         ; => 1
(bar2)                         ; => 9
foo1                           ; => 1
foo2                           ; => 9
(ignore-errors foo3)           ; => nil
(ignore-errors foo4)           ; => nil
```

マクロ化して設定に書いておくと、面倒な記述を減らしてスマートになりますね。