C ++ 14のラムダの新機能

関数型プログラミングが現代のプログラミング言語で急速に普及していることは誰もが知っています。 最近の例はJava 8とC ++で、どちらもラムダ関数をサポートしています。



それでは、始めましょう(そして楽しみが一緒に来るかもしれません)。 このテキストはSlideshareのスライドとしても利用できます。 この記事の著者は、JSONの作成者Douglas Crockfordに触発されました。



引数を取り、同じ引数を返すIdentity関数:



auto Identity = [](auto x) { return x; }; Identity(3); // 3
      
      





翻訳者注 :C ++ 11と比較して新しいのは、型名を指定しない機能です。



関数add、sub、およびmulは、2つの引数を取り、それぞれ合計、差、積を返します。



 auto add = [](auto x, auto y) { return x + y; }; auto sub = [](auto x, auto y) { return x - y; }; auto mul = [](auto x, auto y) { return x * y; };
      
      





引数を取り内部クラスのインスタンスを返すidentityf関数を呼び出すと、元の引数が返されます。



 auto identityf = [](auto x) { class Inner { int x; public: Inner(int i): x(i) {} int operator() () { return x; } }; return Inner(x); }; identityf(5)(); // 5
      
      





オブジェクトではなく関数を返す別のidentityf実装(はい、関数を返すことができるようになりました):



 auto identityf = [](auto x) { return [=]() { return x; }; }; identityf(5)(); // 5
      
      





注:ラムダ関数≠クロージャ:



指定された間隔から数値を返すジェネレーター関数を返す関数:



 auto fromto = [](auto start, auto finish) { return [=]() mutable { if(start < finish) return start++; else throw std::runtime_error("Complete"); }; }; auto range = fromto(0, 10); range(); // 0 range(); // 1
      
      





一度に1つずつ番号を取り、それらを追加する関数:



 auto addf = [](auto x) { return [=](auto y) { return x+y; }; }; addf(5)(4); // 9
      
      





別の関数の引数を交換する関数:



 auto swap =[](auto binary) { return [=](auto x, auto y) { return binary(y, x); }; }; swap(sub)(3, 2); // -1
      
      





バイナリ関数を受け取り、バイナリに引数を2回渡す単項関数を返す2回関数:



 auto twice =[](auto binary) { return [=](auto x) { return binary(x, x); }; }; twice(add)(11); // 22
      
      





バイナリ関数を受け取り、2つの引数を順番に受け取る関数を返す関数:



 auto applyf = [](auto binary) { return [=](auto x) { return [=](auto y) { return binary(x, y); }; }; }; applyf(mul)(3)(4); // 12
      
      





バイナリ関数と引数を取り、2番目の引数を取る関数を返すカレー関数:



 auto curry = [](auto binary, auto x) { return [=](auto y) { return binary(x, y); }; }; curry(mul, 3)(4); // 12
      
      





注: カリー化 (schrying、schönfinkeling)は、いくつかの引数を取る関数を、1つの引数を取る関数のチェーンに変換することです。



関数の部分的な使用:



 auto addFour = [](auto a, auto b, auto c, auto d) { return a+b+c+d; }; auto partial = [](auto func, auto a, auto b) { return [=](auto c, auto d) { return func(a, b, c, d); }; }; partial(addFour,1,2)(3,4); //10
      
      





3つのオプション、新しい関数を作成せずに引数に1を追加する関数を取得する方法:



 auto inc = curry(add, 1); auto inc = addf(1); auto inc = applyf(add)(1);
      
      





機能の構成の実装:



 auto composeu =[](auto f1, auto f2) { return [=](auto x) { return f2(f1(x)); }; }; composeu(inc1, curry(mul, 5))(3) // (3 + 1) * 5 = 20
      
      





バイナリ関数を受け取り、一度しか呼び出せないように変更する関数:



 auto once = [](auto binary) { bool done = false; return [=](auto x, auto y) mutable { if(!done) { done = true; return binary(x, y); } else throw std::runtime_error("once!"); }; }; once(add)(3,4); // 7
      
      





バイナリ関数を受け取り、2つの引数とコールバックを受け取る関数を返す関数:



 auto binaryc = [](auto binary) { return [=](auto x, auto y, auto callbk) { return callbk(binary(x,y)); }; }; binaryc(mul)(5, 6, inc) // 31 binaryc(mul)(5, 6, [](int a) { return a+1; }); //   
      
      





最後に、次の3つの関数を作成します。



 auto unit = [](auto x) { return [=]() { return x; }; }; auto stringify = [](auto x) { std::stringstream ss; ss << x; return unit(ss.str()); }; auto bind = [](auto u) { return [=](auto callback) { return callback(u()); }; };
      
      





次に、すべてが機能することを確認します。

 std::cout << "Left Identity " << stringify(15)() << "==" << bind(unit(15))(stringify)() << std::endl; std::cout << "Right Identity " << stringify(5)() << "==" << bind(stringify(5))(unit)() << std::endl;
      
      





ユニットとバインド関数について何がそんなに面白いですか? 実際、これはモナドです。



著者のブログシリーズ2番目の投稿を読んでください。



All Articles