object)は、プログラミング言語において、関数(サブルーチンないしプロシージャ)を、オブジェクトとしたものである。手続きオブジェクトとも言う(プロシージャ=手続き)[要出典]。ここでのオブジェクトの語は、いわゆるオブジェクト指向のそれに限らず、「第一級オブジェクト」という語におけるのと同じ、メモリ上に領域を確保されたもの、といった意味である。関数が第一級オブジェクトである場合は特に第一級関数と言う。いったような、通常のサブルーチン呼び出しと全く同じ構文で、関数オブジェクトが保持しているサブルーチンを呼び出せる言語もある。通常のサブルーチンのように呼び出すことはできず、applyといった特別な名前のメソッドを経由して呼び出す必要のある言語もある。変数束縛が閉じられた関数オブジェクトはクロージャである。C#などの.NET言語には関数オブジェクトのようなものとして、オブジェクトのインスタンスとその振る舞いであるメソッドとを結びつけて管理することのできる、デリゲートがある。外部リンク用途[編集]関数オブジェクトの典型的な用途は、より優れたコールバックを記述することである。C言語では、コールバックには関数へのポインタを使う他ないが、コールバックの内外で状態変数を共有できない。この制限のために、関数の動的な振る舞いやインターフェイス設計が制約されてしまう。perform_process(&handler);}コールバック関数内で外部の状態変数を参照するためには、グローバル変数を利用したり、構造体メンバーに状態変数へのポインタを持たせたうえでコールバック関数の引数を経由して状態変数のアドレスを渡したり、といった工夫が必要になる。関数オブジェクトは、上記のように煩雑になりがちな設計パターンを言語機能として組み込み、関数を可搬性の高いオブジェクトとして容易に利用できるようにするものである。LISPや、Smalltalk、C++、Java、C#、Perl、Python、Rubyなどの現代的なオブジェクト指向言語は、ほとんどが関数オブジェクト、あるいは同等の機能をサポートしており、さらに有意義な使い方をしているものもある[要追加記述]。起源[編集]関数オブジェクトは、LISPにおいてその初期から研究された。計算機プログラムの構造と解釈の第3章でも解説されている。おいて、ブロックが関数オブジェクトの記法となるよう設計された。配列の各要素を通常の大小関係とは違う順序で並べ替えたい場合、比較のための関数オブジェクトを引数に取るソートメソッドを、引数としてブロックを付けて、呼び出す。ブロック内には、カスタマイズ版の比較手続きを記述する。ソートメソッド内での比較は、渡された関数オブジェクトの手続きを呼び出すことで行なわれ、期待する大小関係でのソートが行なわれる。振る舞いを促進するものである。関数オブジェクト[編集]C++では、クラスあるいは構造体において関数呼び出し演算子の多重定義が可能となっている。具体的には、任意の引数を持つoperator()メンバー関数を定義することで、そのオブジェクトのインスタンスを指す変数の名前が、あたかも関数名(関数指示子)であるかのような構文で、定義した関数を呼ぶことができる。以下のように呼び出すことも可能だが、通例使われない。3);C++のclass/structは、デフォルトのアクセスレベル(アクセス修飾子(英語版))がprivate/publicであるという違いしかないため、関数オブジェクトの記述ではclassの代わりにstructが使われることも多い。配列の中から特定の条件に該当する要素の個数を数えるルーチンの例を考えてみよう。条件の判定処理は自由にカスタマイズできるものとする。プログラムは、たとえば下記のようになる。&isEven));}一方、C++の関数オブジェクトを利用すると下記のようになる。関数テンプレートに渡す際、関数へのポインタではなく構造体のインスタンス(関数オブジェクト)を渡していることに注意されたい。上記の例において関数オブジェクトによるカスタマイズを可能にしているのは、テンプレートと関数呼び出し演算子のオーバーロードによる静的ダック・タイピングである。関数テンプレートを実体化する際の字句解析に適合しさえすれば、述語にはどんなオブジェクトでも渡せる。コールバック関数が実行されると、他のメンバー関数と同様に働き、すなわちオブジェクトの他のメンバー(データや関数)に対して完全にアクセスすることができる。別の種類の関数オブジェクトが可能である。メンバーポインタや、テンプレート機能を利用することができ、テンプレートの記述力により、(関数の合成などの)別種の関数オブジェクトを定義するといったいくつかの関数型言語の技法を用いることができる。して関数オブジェクトを多用している。関数オブジェクトは、「関数呼び出しと同じ構文で、メンバ関数を呼ぶことができるオブジェクト」として実装されている。MLのfunctorや、数学における関手とは関係ない(と考えたほうが良い)。あるオブジェクトが「ファンクタ」である、と説明される[1]。離れた文脈では、関数オブジェクトすなわちファンクタ、ではないので注意。おける関数オブジェクトの利点のひとつは、関数ポインタと異なり、インライン化できるためパフォーマンスが良い点である。for_each()も期待通りの動作をするが、最初の方法では以下のように展開される。IncrementFunctor)二番目の方法では以下のように展開される。場合にはコンパイル時に関数が不定でありインライン化できない。現実には、コンパイラに指示すれば簡単に関数を既知にすることができる。コンパイラが関数の定義を認識しており、それがクラスの内外いずれでも同じように行われていさえすればよい。インライン化しない場合、リンカは関数がクラスの関数だとの指示さえあれば同じ関数の別のコンパイル単位の複数回の定義をエラーを生成せずに黙って見過ごす。リンカは同じ関数の定義がクラスの関数でない場合には複数回の定義を許容しないためである。ひとつの例として、std::sort()関数テンプレートを挙げる。});}std::qsort()およびstd::sort()の実装はいずれもクイックソートとは限らず、処理系依存のため、直接性能を比較することに意味はないが、通例インライン展開が利用できるstd::sort()のほうが性能が良くなる。述語に関数ポインタを利用するよりも、関数オブジェクトを利用したほうが性能が良くなる。C++11で追加されたラムダ式は、コンパイラによって内部的には関数オブジェクトの定義に展開されるため、通例関数オブジェクトを利用した場合と同等の性能になる。状態の保持[編集]関数オブジェクトの利点の一つは、関数の呼び出しをまたいで状態を(オブジェクトのフィールドとして)保持できる点である。回呼び出し結果を出力している。0;}関数オブジェクトで状態を保持する場合、明示的にメンバー変数を定義したうえで、関数オブジェクトのメンバーとして操作を記述しなければならなかった。C++11で導入されたラムダ式では、外部の変数のキャプチャをサポートし、クロージャを実現することができる。ラムダ式によってキャプチャされた変数は、コンパイラによって暗黙的に生成される関数オブジェクトのメンバー変数となる。(プログラミング)」を参照D言語の関数オブジェクト[編集]D言語には関数オブジェクトとして、デリゲートとクロージャの両方がある。&needleTest));}D言語におけるデリゲートとクロージャの違いは、コントロールが変数のスコープから一旦抜けても、変数の寿命が続いているか、そうでないかである。コンパイラにより保守的に、自動的に決定される(後から変数を参照する可能性があればクロージャとする)。D言語は、関数リテラルやラムダ式もサポートしている。needle));}コンパイラがインライン化できるようにするため(上記参照)、関数オブジェクトをC++形式の演算子のオーバーロードを用いて宣言することもできる。D言語ではテンプレート引数として関数等を渡す手法が一般的である。おける関数オブジェクト[編集]Javaでは関数が第一級オブジェクトでないため、関数オブジェクトの代わりとして、一つのメソッドを持つインタフェースが使われる。代表的なインタフェースとしては、run()メソッドを持つjava.lang.Runnableが挙げられる。リストと、意味的には関数を引数にとる。この関数はリスト内のオブジェクトを比較する役割を持つ。Javaは関数が第一級オブジェクトでないため、java.util.Comparatorインタフェースを実装したオブジェクトを渡す。実装する匿名クラスを定義して利用。8からは匿名クラスの糖衣構文としてラムダ式をサポートする。ラムダ式を利用すると、以下のように簡潔に記述することができる。8はメソッド参照もサポートするようになった。メソッド参照は、内部的にはインタフェースを利用して実装されている。おける関数オブジェクト[編集]Pythonでは、関数は、文字列や数値、リストなどをはじめとする他の任意のデータと同様のオブジェクトである。Pythonは第一級関数を扱うことができる言語である。メソッドを持つ任意のオブジェクトを関数呼び出しの構文で呼び出すことができる。関数オブジェクトを定義するもう一つの方法として、ネストした関数定義、といった形の構文を使う方法がある。関数リテラルに相当するものがなく、手続き的なものは名前を付けて定義しなければならない。これはそうするのが良いプラクティスとされているからである。おいても、関数は、文字列やベクトル・リスト・数値と同様に変数に入れたり関数から返したりできる第一級オブジェクトであり、第一級関数を扱うことができる言語である。problem)が認識されることとなった。特殊形式ではクロージャが作られる。変数と関数で名前空間が分かれておらず、変数名を関数名と同様に使ってプログラムを書くことができる。Schemeのように出力される。変数と関数で名前空間が分かれている。Lispのように出力される。名前に対して、変数としての値と、関数とが別々に結びつけられていて、文脈により(カッコ内の並びの先頭にあるか、そうでないかにより)どちらかがアクセスされる。名前の前に付けている。書いても、その名前の関数がないというエラーになる。関数を使って呼び出す。限らず現代的なプログラミング言語の設計において話題になる。現代的な関数型言語では当然のように同じ名前空間である。ローカル変数とメソッドで別の名前空間とした。クラスのローカルインスタンスメソッドを「グローバル関数」と呼んでいるといった例外はあるが、関数は存在せず、全てメソッドである。メソッドはオブジェクトではなく、変数とメソッドで名前空間が違う。メソッドの他に手続きの表現としてブロックがある。ブロックは、メソッド呼び出しにオプショナルに付加できるもので、暗黙の引数といったような感じで呼び出されるメソッドに渡される。いう特殊なグローバル関数により、そのクロージャを呼ぶことができる。ブロックは直接にはオブジェクトではない。オブジェクトとして得ることができる。オブジェクトをブロックの代わりに渡すこともできる。いうインスタンスメソッドにより呼ぶことができる[2]。オブジェクトは文脈という環境を持つ関数オブジェクト状のものである。