Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Select an option

  • Save ROCKTAKEY/f0cd1b21a383ba567624d680790475b1 to your computer and use it in GitHub Desktop.

Select an option

Save ROCKTAKEY/f0cd1b21a383ba567624d680790475b1 to your computer and use it in GitHub Desktop.
(require 'cl-lib) ; `cl-letf', `cl-flet'
(require 'cl) ; `flet'
(defun func1 ()
"`original'というシンボルを返すだけの関数。"
'original)
(defun print-func1 ()
"`func1'を呼び出したときの返り値を表示する関数。"
(message "%s" (func1)))
(defun modify-func1-by-flet ()
"`flet'を使って`func1'を上書きした上で`print-func1'を実行。
`flet'は中で呼び出した`print-func1'においても`func1'を変更する。
`flet'での束縛では、外側で束縛すると内側の全てに波及し、
そのスコープを出ていけばなにもなかったことになる。このような挙動は動的束縛、
dynamic bindingと呼ぶ。
"
(flet ((func1 () 'modified))
(print-func1)))
(modify-func1-by-flet) ; modified
(defun modify-func1-by-cl-flet ()
"`cl-flet'を使って`func1'を上書きした上で`print-func1'を実行。
`flet'は中で呼び出した`print-func1'においては`func1'を変更しない。
なお、`cl-flet'の中で`func1'を直接呼び出せば上書き済みのものとなる。
このように字句通りにしか値を読み出さない挙動から、このような変数や関数の束縛を字句的束縛、
lexical bindingと呼ぶ。"
(cl-flet ((func1 () 'modified))
(print-func1)))
(modify-func1-by-cl-flet) ; original
(defun modify-func1-by-cl-flet ()
"`cl-letf'を使って`func1'を上書きした上で`print-func1'を実行。
`cl-letf'は中で呼び出した`print-func1'においても`func1'を変更する。
`cl-letf'は`flet'と同様に動的束縛を行う。
ただし、関数に限らず、変数や、変数の一部分など様々なもの(ジェネリック変数と呼ばれる)を動的束縛できる。
変数の場合は通常の`let'のように使える。
ジェネリック変数については以下を参照。
https://ayatakesi.github.io/lispref/28.2/elisp-ja.html#Setting-Generalized-Variables"
(cl-letf (((symbol-function 'func1) (lambda () 'modified)))
(print-func1)))
(modify-func1-by-cl-flet) ; modified
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment