Next: , Previous: , Up: Functions   [Contents][Index]


12.5 Calling Functions

関数を定義しただけでは、半分しか終わっていません。関数はそれを呼び出す(call) — たとえば実行(run)するまでは、何も行いません。関数のcallは、invocationとしても知られています。

関数を呼び出すもっとも一般的な方法は、リストの評価による方法です。たとえば、リスト(concat "a" "b")を評価することにより、関数concatが引数"a""b"で呼び出されます。評価については、Evaluationを参照してください。

プログラム内で式としてリストを記述するときは、プログラム内にテキストで、どの関数を呼び出すか、いくつの引数を与えるかを指定します。通常は、これが行いたいことです。どの関数を呼び出すかを、実行時に計算する必要がある場合もあります。これを行うには、関数funcallを使用します。実行時にいくつの引数を渡すか決定する必要があるときは、applyを使用します。

Function: funcall function &rest arguments

funcallは、関数functionを引数argumentsで呼び出し、functionがreturnした値をreturnします。

funcallは関数なので、functionを含むすべての引数は、funcallの呼び出し前に評価されます。これは、呼び出される関数を得るための任意の式を使用できることを意味します。これはまた、funcallargumentsに記述した式ではなく、その値だけを見ることを意味します。これらの値はfunction呼び出し中では、2回目は評価されませんfuncallの処理は、関数の通常の呼び出し手続きと似ており、すでに評価された引数は評価されません。

引数functionは、Lisp関数、またはプリミティブ関数でなければなりません。つまりスペシャルフォームやマクロは、“評価されていない”引数式を与えられたときだけ意味があるので、指定することはできません。上述したように、funcallは最初に指定された評価前の引数を提供することはできません。

(setq f 'list)
     ⇒ list
(funcall f 'x 'y 'z)
     ⇒ (x y z)
(funcall f 'x 'y '(z))
     ⇒ (x y (z))
(funcall 'and t nil)
error→ Invalid function: #<subr and>

これらの例を、applyの例と比較してみてください。

Function: apply function &rest arguments

applyは、関数functionを引数argumentsで呼び出します。これはfuncallと同様ですが、1つ違いがあります。argumentsの最後はオブジェクトのリストです。これは1つのリストではなく、個別の引数としてfunctionに渡されます。わたしたちはこれを、applyがこのリストを展開(spread)(個々の要素が引数となるので)する、と言います。

applyは、functionを呼び出した結果をreturnします。funcallと同様、functionはLisp関数かプリミティブ関数でなければなりません。つまりスペシャルフォームやマクロは、applyでは意味をもちません。

(setq f 'list)
     ⇒ list
(apply f 'x 'y 'z)
error→ Wrong type argument: listp, z
(apply '+ 1 2 '(3 4))
     ⇒ 10
(apply '+ '(1 2 3 4))
     ⇒ 10

(apply 'append '((a b c) nil (x y z) nil))
     ⇒ (a b c x y z)

applyを使用した興味深い例は、Definition of mapcarを参照してください。

ある関数にたいして、その関数のある引数を特定の値に固定し、他の引数は実際に呼びだされたときの値にできれば便利なことがあります。関数のいくつかの引数を固定することは、その関数の部分適用(partial application)と呼ばれます9。結果は、残りの引数をとる新たな関数で、すべての引数を合わせて元の関数を呼び出します。

Emacs Lispで部分適用を行う方法を示します:

Function: apply-partially func &rest args

この関数は、新たな関数をreturnします。この新しい関数は、呼びだされたときにargsと、呼び出し時に指定された追加の引数から成る引数リストでfuncを呼び出す関数です。funcn個の引数を指定できる場合、m < n個の引数でapply-partiallyを呼び出すと、n - m個の新たな関数を生成します。

以下は、apply-partiallyと他のビルトイン関数+,を使用して、(もし存在しないなら)ビルトイン関数1+を定義する例です:

(defalias '1+ (apply-partially '+ 1)
  "Increment argument by one.")
(1+ 10)
     ⇒ 11

引数として関数をとったり、データ構造(特にフック変数やプロパティーリスト)から関数を探す関数はLispでは一般的で、それらはfuncallapplyを使用してそれらの関数を呼び出します。引数として関数をとる関数は、ファンクショナル(functional)と呼ばれるときもあります。

ファンクショナルを呼び出すとき、引数としてno-op関数(何も行わない関数)を指定できると便利なときがあります。以下に2つの異なるno-op関数を示します:

Function: identity arg

この関数はargをreturnします。副作用はありません。

Function: ignore &rest args

この関数は任意の引数を無視して、nilをreturnします。

いくつかの関数はユーザーに可視なコマンドで、これらは(通常はキーシーケンスを介して)対話的に呼び出すことができます。そのようなコマンドは、call-interactively関数を使用することにより、対話的に呼びだされたときと同様に呼び出すことができます。Interactive Callを参照してください。


Footnotes

(9)

これはカリー化(currying)と関連しますが、異なる機能です。カーリングは、複数の引数をとる関数を、関数チェーンとして呼び出せるような、1つの引数を取る個々の関数に変換するような方法です。