これまでのところ私は聞いた:
これはすべて関数型プログラミングに関連しているようです...
どうやらそれはC++ 1xに統合されるので、私はそれを今よりよく理解するかもしれません:
http://en.wikipedia.org/wiki/C%2B%2B0x#Lambda_functions_and_expressions
誰かがラムダのものとは何かを簡単に定義し、それが役立つ場所を与えることができますか?
ラムダ計算は、30年代にアロンツォ教会によって発明された計算モデルです。ほとんどの関数型プログラミング言語の構文とセマンティクスは、ラムダ計算に直接または間接的に影響を受けています。
最も基本的な形式のラムダ計算には、抽象化((無名)関数の作成)とアプリケーション(関数の適用)の2つの操作があります。抽象化はλ演算子を使用して実行され、ラムダ計算にその名前が付けられます。
匿名関数は、「ラムダ」、「ラムダ関数」、または「ラムダ式」と呼ばれることがよくあります。これは、前述のように、λはラムダ計算で匿名関数を作成するための記号でした(そして、Wordのlambda
は、同じ理由でLISPベースの言語)。
これはよく使われる用語ではありませんが、無名関数を使用したプログラミングまたは高階関数を使用したプログラミングを意味すると思います。
C++ 0xのラムダ、それらの動機、および関数ポインターとの関係についてのもう少し詳しい情報(これの多くはおそらくあなたがすでに知っていることの繰り返しですが、ラムダの動機とそれらの違いを説明するのに役立つことを願っています関数ポインタから):
すでにCに存在していた関数ポインタは、たとえば、比較関数をソート関数に渡します。ただし、それらの有用性には制限があります。
たとえば、ベクトルのベクトルを各ベクトルのi
th要素で並べ替える場合(i
はランタイムパラメーターです)、これを関数ポインターで解決することはできません。 2つのベクトルをi
th要素で比較する関数は3つの引数(i
と2つのベクトル)を取る必要がありますが、並べ替え関数は2つの引数を取る関数が必要です。必要なのは、何らかの方法で引数i
を関数に渡してから、それを並べ替え関数に渡す方法ですが、プレーンなC関数ではこれを行うことはできません。
これを解決するために、C++は「関数オブジェクト」または「ファンクター」の概念を導入しました。ファンクタは基本的にoperator()
メソッドを持つオブジェクトです。これで、クラスCompareByIthElement
を定義できます。これは、引数i
をコンストラクター引数として受け取り、比較する2つのベクトルをoperator()
メソッドの引数として受け取ります。 i
th要素でベクターのベクターを並べ替えるには、CompareByIthElement
を引数としてi
オブジェクトを作成し、そのオブジェクトを並べ替え関数に渡すことができます。
関数オブジェクトは単なるオブジェクトであり、技術的な関数ではないので(たとえそれらがそのように動作するように意図されていても)、関数ポインターを関数オブジェクトにポイントすることはできません(もちろん、関数オブジェクトへのポインターを持つことはできますが、 _CompareByIthElement*
_のような型を持つため、関数ポインターではありません)。
関数を引数として取るC++標準ライブラリのほとんどの関数は、関数ポインターだけでなく関数オブジェクトでも機能するようにテンプレートを使用して定義されます。
今ラムダに:
クラス全体を定義してi
th要素で比較することは、ベクトルをソートするために一度だけ使用する場合は少し冗長です。関数ポインターのみが必要な場合でも、名前付き関数の定義は、a)ネームスペースを汚染し、b)関数は通常非常に小さく、実際には存在しないため、一度しか使用されない場合は最適とは言えません。ロジックをそれ自体の関数に抽象化する正当な理由(関数を定義せずに関数ポインターを持つことはできません)。
したがって、このラムダを修正するために導入されました。ラムダは関数オブジェクトであり、関数ポインタではありません。 [x1, x2](y1,y2){bla}
のようなラムダリテラルを使用すると、基本的に次のことを行うコードが生成されます。
x1
_および_x2
_)と、引数(_y1
_および_y2
_)および本体bla
を持つoperator()
を持つクラスを定義します。x1
_および_x2
_を現在スコープ内にある変数_x1
_および_x2
_の値に設定します。したがって、ラムダは、ラムダを使用する以外の方法でラムダを実装するために生成されたクラスにアクセスできないことを除いて、関数オブジェクトのように動作します。したがって、ファンクタを引数として受け入れる関数(基本的には標準ライブラリの非C関数を意味します)はラムダを受け入れますが、関数ポインタのみを受け入れる関数は受け入れません。
基本的に、ラムダ関数は「オンザフライ」で作成する関数です。 C++ 1xでは、関数型プログラミングのサポートを改善するために使用できます。
_std::for_each( begin, end, [](int i){std::cout << i << '\n';} );
_
これにより、おおよそ次のようなコードが生成されます。
_struct some_functor {
void operator()(int i) {std::cout << i << '\n';}
};
std::for_each( begin, end, some_functor() );
_
std::for_each()
へのこの1回の呼び出しだけで_some_functor
_が必要な場合、そのラムダ関数にはいくつかの利点があります。
ラムダ関数は、無名関数の別の名前です-基本的に名前のない関数です。
通常、これは関数を1回だけ使用する必要がある言語で使用します。たとえばの代わりに
def add(a, b)
return a+b
そしてその関数を別の関数に渡す
reduce(add, [5,3,2])
ラムダを使用すると、単純に
reduce(lambda x, y: a+b, [5,3,2])