Next: , Previous: , Up: 変数束縛   [Contents][Index]


4.3.3 関数束縛

これらのフォームは変数の代わりに関数にletに似た束縛を作る。

Special Form: flet (bindings…) forms…

このフォームは値セルではなくシンボルの関数セルにletスタイルの 束縛を確立する。それぞれのbindingはフォーム ‘(name arglist forms…)’の リストでなければならない。それは正確にdefun* フォームであるかのように関数を定義する。関数namefletの 本体の間だけそれに応じて定義される; それから古い関数定義や 関数定義がないことが戻される。

Common Lispのfletnameのレキシカルな束縛を確立するが、 Emacs Lispのfletは動的束縛を作る。その結果、fletfletフォーム自身の内部での直接的な呼び出しと同様に間接的な関数 への呼び出しに影響する。

一時的な仕方で関数の振る舞いを無効にしたり修正したりするために 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 プログラム構造.

Special Form: labels (bindings…) forms…

labelsフォームはfletと似ているが、動的束縛ではなく 関数名のレキシカルな束縛を作る点が異なる。(真のCommon Lispでは、 fletlabelsのどちらもわずかに異なる種類のレキシカルな 束縛を作る; Emacs Lispは既定では動的束縛なので、fletのためにも 動的束縛を使うことはより適切に見える。labelsフォームは レキシカルな束縛を持っており、Common Lispと完全に互換である。)

レキシカルスコープは、名付けられた関数へのすべての参照は物理的に labelsフォームの本体内に現れなくてはならないことを意味する。 参照はlabels自身の本体formsの中にも関数自身の本体の中にも 現れてよい。したがって、labelsは局所再帰関数や相互再帰関数の 集合を定義できる。

関数名への“参照”はその関数への呼び出しか、たとえばmapcarへ 渡されるためにquotefunctionに引用されたその名前の 使用である。