これらのフォームは変数の代わりに関数にlet
に似た束縛を作る。
このフォームは値セルではなくシンボルの関数セルにlet
スタイルの
束縛を確立する。それぞれのbindingはフォーム
‘(name arglist forms…)’の
リストでなければならない。それは正確にdefun*
フォームであるかのように関数を定義する。関数nameはflet
の
本体の間だけそれに応じて定義される; それから古い関数定義や
関数定義がないことが戻される。
Common Lispのflet
はnameのレキシカルな束縛を確立するが、
Emacs Lispのflet
は動的束縛を作る。その結果、flet
は
flet
フォーム自身の内部での直接的な呼び出しと同様に間接的な関数
への呼び出しに影響する。
一時的な仕方で関数の振る舞いを無効にしたり修正したりするために
flet
を使うことができる。これはEmacsプリミティブ上でも
動作するが、Emacs内部のプリミティブ関数へのいくつかの呼び出しは
シンボルの関数セルを通さずに行なわれるので、flet
によって
影響されないことに注意せよ。たとえば、
(flet ((message (&rest args) (push args saved-msgs))) (do-something))
このコードはメッセージを表示するのではなく、単にリストにセーブする
関数で組み込み関数message
を置き換えようと試みる。message
のオリジナルの定義はdo-something
の脱出の後に戻される。この
コードは他のLispコードによって生成されるメッセージにはうまく働くが、
Emacs内部で直接生成されるメッセージはLispのmessage
関数を
通じてではなくメッセージルーチンへの直接のC言語呼び出しを行なうので、
それらは捉えられない。
flet
で定義された関数はdefun*
によってサポートされている
完全なCommon Lisp引数表記法を使ってもよい; また、関数本体は
defun*
のように暗黙のブロックに囲まれる。See プログラム構造.
labels
フォームはflet
と似ているが、動的束縛ではなく
関数名のレキシカルな束縛を作る点が異なる。(真のCommon Lispでは、
flet
とlabels
のどちらもわずかに異なる種類のレキシカルな
束縛を作る; Emacs Lispは既定では動的束縛なので、flet
のためにも
動的束縛を使うことはより適切に見える。labels
フォームは
レキシカルな束縛を持っており、Common Lispと完全に互換である。)
レキシカルスコープは、名付けられた関数へのすべての参照は物理的に
labels
フォームの本体内に現れなくてはならないことを意味する。
参照はlabels
自身の本体formsの中にも関数自身の本体の中にも
現れてよい。したがって、labels
は局所再帰関数や相互再帰関数の
集合を定義できる。
関数名への“参照”はその関数への呼び出しか、たとえばmapcar
へ
渡されるためにquote
やfunction
に引用されたその名前の
使用である。