誰もが話し続けるこの「ラムダ」とは何ですか?多くの人がそれを気に入っているようですが、そこから収集できるのは、コードの多くの行を1つの式に詰め込む方法にすぎないということだけです。
誰かがその真の価値について私に教えてもらえますか?
簡単に言えば、ラムダは名前のない関数、または無名関数です。変数であるかのように渡すことができる実行可能コードの小さな部分。 JavaScriptの場合:
function () {}; // very simple
これらのラムダのいくつかの使用法を見てみましょう。
ラムダは、ボイラープレートコードを抽象化するために使用できます。たとえば、ループ。私たちは一日中for
とwhile
のループを書くのに慣れています。しかし、これは書かれていないコードです。ループの最も重要な部分であるループ内のコードを抽出し、残りを抽象化することができます。
for (var i=0; i<array.length; i++) {
// do what something useful with array[i]
}
配列オブジェクトの forEach
を使用すると、次のようになります。
array.forEach(function (element, index) {
// do something useful with element
// element is the equivalent of array[i] from above
});
上記の抽象化はそれほど有用ではないかもしれませんが、forEach
のように、はるかに有用なタスクを実行する他の高階関数があります。例 filter
:
var numbers = [1, 2, 3, 4];
var even = [];
// keep all even numbers from above array
for (var i=0; i<numbers.length; i++) {
if (numbers[i] % 2 === 0) {
even.Push(numbers[i]);
}
}
alert(even);
// Using the filter method
even = [1, 2, 3, 4].filter(function (number) {
return number % 2 === 0;
});
alert(even);
イベントの概念が利用できる一部の環境では、ラムダを使用して、ある時点で発生する可能性のあるイベントに応答できます。
window.onload = function () {
alert("Loaded");
};
window.setTimeout(function () {
alert("Code executed after 2 seconds.");
}, 2000);
これは他の方法で行うこともできますが、それらはかなり冗長です。たとえば、Javaには、Runnable
インターフェイスがあります。
この時点まで、私たちは主にその構文糖衣機能にラムダのみを使用していました。ただし、ラムダの方がはるかに役立つ場合があります。たとえば、ラムダを返す関数があるかもしれません。戻り値をキャッシュしたい関数があるとしましょう。
var users = [];
var getUser = function (name) {
if (! users[name]) {
// expensive operations to get a user. Ajax for example
users[name] = user_from_ajax;
}
return users[name];
};
後で、同様の機能があることに気付くかもしれません。
var photos = [];
var getPhoto = function (name) {
if (! photo[name]) {
// expensive operations to get a user. Ajax for example
photos[name] = photo_from_ajax;
}
return photos[name];
};
そこには明らかにパターンがあるので、それを抽象化しましょう。 メモ化 を使用しましょう。
/**
* @param {Array} store Data structure in which we cache lambda's return values
* @param {Function} lambda
* @return {Function} A function that caches the result of calling the lambda param
*/
var memoize = function (store, lambda) {
// return a new lambda
return function (name) {
if (! store[name]) {
// Execute the lambda and cache the result
store[name] = lambda(name);
}
return store[name];
};
};
var getUsers = memoize([], function (name) {
// expensive operations to get a user. Ajax for example
});
var getPhotos = memoize([], function (name) {
// expensive operations to get a photo. Ajax for example
});
ご覧のとおり、ラムダを使用することで、キャッシュ/メモ化ロジックを抽象化することができました。他の例でいくつかの回避策があった場合、この特定の問題は他の手法ではほとんど解決されないと思います。重要な定型コードを1か所に抽出することができました。言うまでもなく、users
およびphotos
グローバル変数を削除しました。
あなたのプロフィールを見ると、あなたはほとんどPythonユーザーです。上記のパターンでは、Pythonはデコレータの概念を持っています。 メモ化のためのネット上の例 デコレータ。唯一の違いは、Pythonにという名前が付けられている可能性が高いことですそのデコレータ関数内にネストされた関数。その理由はPythonは単一式のラムダのみをサポートするためです。しかし、概念は同じです。
Pythonラムダの使用の例として。偶数をフィルタリングした上記のコードは、次のようにPythonで表すことができます:
filter(lambda x: x % 2 == 0, [1, 2, 3, 4])
とにかく、ラムダはクロージャなしではそれほど強力ではありません。クロージャは、ラムダの概念を非常に強力にするものです。メモ化の例では、クロージャを使用してstore
パラメータの周りにクロージャを作成しました。このようにして、memoize
関数が結果(ラムダ)を返した後でも、そのパラメーターにアクセスできます。
「ラムダ」という用語は、無名関数、通常は クロージャ を指すために使用されます。これらは、コードを不必要に肥大化させることなく、他の関数を使用する関数を記述できるので便利です。たとえば、Rubyでは次のようになります。
(1..100).select {|num| num % 2 == 0}
これにより、1〜100の偶数を含む配列が作成されます。明示的なループを書き出す必要はありません。selectメソッドは値のテストに使用する関数を受け取るため、必要なのはカスタムロジックだけです。これにより、実質的に労力やオーバーヘッドなしでメソッドを大幅にカスタマイズできます。基本的に、小さな関数から関数を構成することができます。
それは彼らができることの簡単な例です。関数をデータとして渡す機能は非常に強力であり、関数型言語プログラマーは日常的にそれを使っていくつかの本当に驚くべきことをします。
「ラムダ」は少なすぎるかもしれません。 ラムダ計算 を見てください。関数型プログラミングに役立ちます。
また、関数型プログラミングは、さらに別のプログラミングパラダイムです(手続き型またはオブジェクト指向など)。
.NETのラムダは、「シンタックスシュガー」と呼ばれることがよくあります。それらは機能に直接影響を与えませんが、人々が言語を使いやすくします。
それらを使用することの力を理解すると、デリゲート/匿名メソッドを使用する古いスタイルの方法と比較して、記述するコードが少なくなることがわかると思います。
関数ポインタ、デリゲート、ストラテジー、またはオブザーバーのパターン/イベント処理を使用する関数/メソッドを使用したことがあり、「この関数全体を1回だけ使用するために作成しています。つまり、このメソッドに渡します。 ;コードを乱雑にするのではなく、その場で記述できればいいのにと思います」-そこでLambda関数を使用できます。この構成をサポートする言語は、通常、特にリスト(ファーストクラス関数および高階関数)の操作に関して、パラメーターとして関数を渡すという概念を大いに活用します。これは、計算のためにメモリの変更ではなく関数の合成に依存する関数型言語に特に当てはまります。場合によっては(Pythonなどの言語で)、リスト内包表記を使用したラムダ関数の使用も、同等のforeachループよりも読みやすいと見なされます。
Dr Dobbs Journal 便利な ラムダ式を紹介する記事 (C++のコンテキスト内ですが、原則はどの言語にも適用できると思います)。
記事にあるように、「ラムダ式は非常にコンパクトな式であり、個別のクラス/関数定義を必要としません。」
したがって、次のように書く代わりに、 [〜#〜] ddj [〜#〜] のリスト1と2の例を使用します。
std::for_each( vec.begin(), vec.end(), print_to_stream<std::string>(std::cout));
これには、次のような個別のクラス定義が必要です。
template <typename T, typename Stream> class print_to_stream_t {
Stream& stream_;
public:
print_to_stream_t(Stream& s):stream_(s) {}
void operator()(const T& t) const {
stream_ << t;
}
};
template <typename T,typename Stream>
print_to_stream_t<T,Stream> print_to_stream(Stream& s) {
return print_to_stream_t<T,Stream>(s);
}
Boost lambda library を使用すると、次のようになります。
std::for_each(vec.begin(),vec.end(),std::cout << _1);
これにより、定義がインラインに保たれます。
記事 ラムダ式のいくつかのアプリケーションについても説明しています。
DDJの記事 の重要なポイントは、「通常、呼び出しサイトで小さくて過度に複雑でない関数が必要な場合にラムダ式が使用されます。関数が重要な場合は、ラムダ式ですが、通常の関数または関数オブジェクトです。」
'lambda' qua Wordは、コンピューターサイエンスの種類が、コンピューターサイエンスの学位を持つよりも、数学や論理のトレーニングを受ける可能性が高かった時代の用語です。それらのいくつかは、「関数型プログラミング」と呼ばれるパラダイムを作り上げました。これは、命令型とはまったく異なり、非常に強力でもあります。 [〜#〜] afaik [〜#〜] これは、この用語が使用されるようになった環境です。
数学者と論理学者は奇妙な言葉を使うことになります。
「ラムダ」は本当に難解に聞こえます-まるでそれらが非常に奇妙で特別なものであるかのように。実際、Webブラウザーアプリケーション用のJavaScriptを作成し、「var foo = function(){...}」イディオムを使用する場合、ラムダ関数をずっと使用してきました。
ラムダ式は単純な形式の関数です。左側のフォーム(パラメーターに相当)が右側のフォーム(本体に相当)になるという考え方です。
たとえば、cシャープの場合:
x => x * x
値を2乗するラムダです。形の何か
x
何かの形になります
x * x
ラムダ式の詳細については、 Wikipedia も確認してください。 (ラムダ計算とプログラミング言語の部分までスクロールダウンします。)ラムダ式はそれほど新しいものではなく、C#の一部ではなく、ほぼ80年前にコンピューティングに導入されました!ラムダ式は関数型プログラミングの基礎です。
それは価値ですか?まあ、それが実際にはかなり古いことを考えると、私は言うでしょう:計算をしている人にとって非常に価値があります。
Javaに興味がある場合は、この機能をJava 7に追加するためのさまざまな提案があったため、この2か月でラムダまたはクロージャについて多くのことを聞いたことがあると思います。 comiteeはそれを落としました。提案の1つはNealGafterからのものであり、ここで詳細に説明されています: javac.info 。これは、使用例と利点(特に内部クラスよりも)を理解するのに役立ちました。
Javaラムダの場合、これは良い出発点になるかもしれません:
http://rodrigouchoa.wordpress.com/2014/09/10/Java-8-lambda-expressions-tutorial/
「ラムダ式は、式とステートメントを含めることができる無名関数であり、デリゲートまたは式ツリータイプを作成するために使用できます。
すべてのラムダ式はラムダ演算子=>を使用します。これは、「goesto」として読み取られます。ラムダ演算子の左側は入力パラメーター(存在する場合)を指定し、右側は式またはステートメントブロックを保持します。ラムダ式x => x * xは、「xはxのx倍になります」と読み取られます。
from [〜#〜] msdn [〜#〜]
ここから始めるために知っておく必要のあるすべて(C#Lambdasについて)を見つけることができます:
ラムダ式