Next: Declare Form, Previous: Obsolete Functions, Up: Functions [Contents][Index]
インライン関数(inline function)は関数と同様に機能しますが、1つ例外があります。その関数の呼び出しがバイトコンパイルされると(Byte Compilationを参照)、その関数の定義が呼び出し側に展開されます。
インライン関数を定義するには、defunのかわりにdefsubstを記述するのがシンプルに方法です。定義の残りの部分は同一に見えますが、defsubstの使用によりバイトコンパイルにそれをインラインにするように指示します。
このマクロはインライン関数を定義する。マクロの構文はdefunとまったく同じ(Defining Functionsを参照)。
関数をインラインにすることにより、その関数の呼び出しが高速になる場合があります、が欠点もありその1つは柔軟性の減少です。その関数の定義を変更すると、すでにインライン化された呼び出しは、リコンパイルを行うまで古い定義を使用することになります。
もう1つの欠点は、大きな関数をインライン化することにより、コンパイルされたコードのファイル上およびメモリー上のサイズが増大することです。スピード面でのインライン化の有利性は小さい関数で顕著なので、一般的に大きな関数をインライン化するべきではありません。
インライン関数はデバッグ、トレース、アドバイス(Advising Functionsを参照)に際してうまく機能しません。デバッグの容易さと関数の再定義の柔軟さはEmacsの重要な機能なので、スピードがとても重要であってdefunの使用が実際に性能の面で問題となるのか検証するためにすでにコードをチューニングしたのでなければ、たとえその関数が小さくてもインライン化するべきではありません。
インライン関数を定義した後そのインライン展開はマクロ同様、同じファイル内の後の部分で処理されます。
インライン関数が実行するのと同じコードに展開されるマクロ(Macrosを参照してください)を定義するためにdefmacroを使用できます。しかし式内でのマクロの直接の使用には制限があります
—
apply、mapcarなどでマクロを呼び出すことはできません。通常の関数からマクロへの変換には余分な作業が必要になります。通常の関数をインライン関数に変換するのは簡単です。defunをdefsubstに置き換えるだけです。インライン関数の引数はそれぞれ正確に1回評価されるので、マクロのときのようにbodyで引数を何回使用するかを心配する必要はありません。
かわりにコンパイラーマクロとしてインライン展開されるコードを記述することにより関数を定義できます。以下のマクロがこれを可能にします。
自身をインライン化するコードを提供することにより、コンパイラーマクロとして関数nameを定義する。この関数は引数リストargsを受け取り、指定されたbodyをもつ。
docが与えられたなら、それは関数のドキュメント文字列であること(Function Documentationを参照)。declareが与えられたなら、それは関数のメタデータを指定するdeclareフォームであること(Declare Formを参照)。
define-inlineで定義された関数は、defsubstやdefmacroで定義されたマクロにたいして複数の利点をもちます。
mapcarに渡すことができる(Mapping Functionsを参照)。
cl-defsubstより予測可能な方法で振る舞う(Argument Lists in Common Lisp
Extensions for GNU Emacs Lispを参照)。
defmacroと同様に、define-inlineでインライン化された関数は、呼び出し側からダイナミックかレキシカルいずれかのスコーピングルールを継承します。Variable Scopingを参照してください。
以下のマクロはdefine-inlineで定義された関数のbody内で使用する必要があります。
define-inlineにたいしてexpressionをクォートする。これはバッククォート(Backquoteを参照)と似ているが、コードをクォートして,だけを受け入れ、,@は受け入れない。
これはlet (Local Variablesを参照)と似ている。bindingsで指定されたローカル変数をセットアップしてから、その効力の下でbodyを評価する。bindingsの要素はそれぞれシンボルか(var expr)という形式のリストであること。exprを評価した結果をvarにバインドしたものが結果となる。bindingsの終端の要素はnilか引数リストを保持するシンボルが可能。シンボルなら引数はそれぞれ評価されて結果となるリストにシンボルがバインドされる。
expressionの値が既知なら非nilをリターンする。
expressionの値をリターンする。
formatに応じてargsをフォーマットしてエラーをシグナルする。
以下はdefine-inlineを使用した例です:
(define-inline myaccessor (obj)
(inline-letevals (obj)
(inline-quote (if (foo-p ,obj) (aref (cdr ,obj) 3) (aref ,obj 2)))))
これは以下と等価です
(defsubst myaccessor (obj) (if (foo-p obj) (aref (cdr obj) 3) (aref obj 2)))