web-dev-qa-db-ja.com

誰もが話し続けるこの「ラムダ」とは何ですか?

誰もが話し続けるこの「ラムダ」とは何ですか?多くの人がそれを気に入っているようですが、そこから収集できるのは、コードの多くの行を1つの式に詰め込む方法にすぎないということだけです。

誰かがその真の価値について私に教えてもらえますか?

92
Josh Hunt

名前のない関数

簡単に言えば、ラムダは名前のない関数、または無名関数です。変数であるかのように渡すことができる実行可能コードの小さな部分。 JavaScriptの場合:

function () {}; // very simple

これらのラムダのいくつかの使用法を見てみましょう。

ボイラープレートコードの抽象化

ラムダは、ボイラープレートコードを抽象化するために使用できます。たとえば、ループ。私たちは一日中forwhileのループを書くのに慣れています。しかし、これは書かれていないコードです。ループの最も重要な部分であるループ内のコードを抽出し、残りを抽象化することができます。

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関数が結果(ラムダ)を返した後でも、そのパラメーターにアクセスできます。

178
Ionuț G. Stan

「ラムダ」という用語は、無名関数、通常は クロージャ を指すために使用されます。これらは、コードを不必要に肥大化させることなく、他の関数を使用する関数を記述できるので便利です。たとえば、Rubyでは次のようになります。

(1..100).select {|num| num % 2 == 0}

これにより、1〜100の偶数を含む配列が作成されます。明示的なループを書き出す必要はありません。selectメソッドは値のテストに使用する関数を受け取るため、必要なのはカスタムロジックだけです。これにより、実質的に労力やオーバーヘッドなしでメソッドを大幅にカスタマイズできます。基本的に、小さな関数から関数を構成することができます。

それは彼らができることの簡単な例です。関数をデータとして渡す機能は非常に強力であり、関数型言語プログラマーは日常的にそれを使っていくつかの本当に驚くべきことをします。

19
Chuck

「ラムダ」は少なすぎるかもしれません。 ラムダ計算 を見てください。関数型プログラミングに役立ちます。

また、関数型プログラミングは、さらに別のプログラミングパラダイムです(手続き型またはオブジェクト指向など)。

6
H_I

.NETのラムダは、「シンタックスシュガー」と呼ばれることがよくあります。それらは機能に直接影響を与えませんが、人々が言語を使いやすくします。

それらを使用することの力を理解すると、デリゲート/匿名メソッドを使用する古いスタイルの方法と比較して、記述するコードが少なくなることがわかると思います。

5
redsquare

関数ポインタ、デリゲート、ストラテジー、またはオブザーバーのパターン/イベント処理を使用する関数/メソッドを使用したことがあり、「この関数全体を1回だけ使用するために作成しています。つまり、このメソッドに渡します。 ;コードを乱雑にするのではなく、その場で記述できればいいのにと思います」-そこでLambda関数を使用できます。この構成をサポートする言語は、通常、特にリスト(ファーストクラス関数および高階関数)の操作に関して、パラメーターとして関数を渡すという概念を大いに活用します。これは、計算のためにメモリの変更ではなく関数の合成に依存する関数型言語に特に当てはまります。場合によっては(Pythonなどの言語で)、リスト内包表記を使用したラムダ関数の使用も、同等のforeachループよりも読みやすいと見なされます。

2
T.R.

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の記事 の重要なポイントは、「通常、呼び出しサイトで小さくて過度に複雑でない関数が必要な場合にラムダ式が使用されます。関数が重要な場合は、ラムダ式ですが、通常の関数または関数オブジェクトです。」

2
danio

'lambda' qua Wordは、コンピューターサイエンスの種類が、コンピューターサイエンスの学位を持つよりも、数学や論理のトレーニングを受ける可能性が高かった時代の用語です。それらのいくつかは、「関数型プログラミング」と呼ばれるパラダイムを作り上げました。これは、命令型とはまったく異なり、非常に強力でもあります。 [〜#〜] afaik [〜#〜] これは、この用語が使用されるようになった環境です。

数学者と論理学者は奇妙な言葉を使うことになります。

「ラムダ」は本当に難解に聞こえます-まるでそれらが非常に奇妙で特別なものであるかのように。実際、Webブラウザーアプリケーション用のJavaScriptを作成し、「var foo = function(){...}」イディオムを使用する場合、ラムダ関数をずっと使用してきました。

2
Ragin' Genius

ラムダ式は単純な形式の関数です。左側のフォーム(パラメーターに相当)が右側のフォーム(本体に相当)になるという考え方です。

たとえば、cシャープの場合:

x => x * x

値を2乗するラムダです。形の何か

x

何かの形になります

x * x
1
Dave Cousineau

ラムダ式の詳細については、 Wikipedia も確認してください。 (ラムダ計算とプログラミング言語の部分までスクロールダウンします。)ラムダ式はそれほど新しいものではなく、C#の一部ではなく、ほぼ80年前にコンピューティングに導入されました!ラムダ式は関数型プログラミングの基礎です。

それは価値ですか?まあ、それが実際にはかなり古いことを考えると、私は言うでしょう:計算をしている人にとって非常に価値があります。

0
Wim ten Brink

Javaに興味がある場合は、この機能をJava 7に追加するためのさまざまな提案があったため、この2か月でラムダまたはクロージャについて多くのことを聞いたことがあると思います。 comiteeはそれを落としました。提案の1つはNealGafterからのものであり、ここで詳細に説明されています: javac.info 。これは、使用例と利点(特に内部クラスよりも)を理解するのに役立ちました。

0
Tim Büthe

Javaラムダの場合、これは良い出発点になるかもしれません:

http://rodrigouchoa.wordpress.com/2014/09/10/Java-8-lambda-expressions-tutorial/

0
Rodrigo

「ラムダ式は、式とステートメントを含めることができる無名関数であり、デリゲートまたは式ツリータイプを作成するために使用できます。

すべてのラムダ式はラムダ演算子=>を使用します。これは、「goesto」として読み取られます。ラムダ演算子の左側は入力パラメーター(存在する場合)を指定し、右側は式またはステートメントブロックを保持します。ラムダ式x => x * xは、「xはxのx倍になります」と読み取られます。

from [〜#〜] msdn [〜#〜]

0
Fermin

ここから始めるために知っておく必要のあるすべて(C#Lambdasについて)を見つけることができます:
ラムダ式

0
Robert Koritnik