Java
FunctionalProgramming

この記事はGo言語で高階関数を書いて遊んでみたでも登場した某友人の記事クロージャで遊ぶSwiftに対するオマージュです。
(元記事にもある通り)楽しい以外の何でもないので、有益な実装を求めていた方は、ブラウザバック推奨です。

(注)深夜テンションで書いてるので、変な箇所があるかもしれませんがご了承くださいm(_ _)m

本題

hoge1 ~ 4は、返却値がFunctionのため、さらに引数を渡すことができる

// Integerをとり、Integerを返す
Function<Integer, Integer> hoge1 = value -> value;
hoge1.apply(1); // return 1
// Integerをとり、IntegerをとりIntegerを返す関数を返す
Function<Integer, Function<Integer, Integer>> hoge2 = value -> (a -> value + a);
hoge2.apply(1).apply(2);    // return 3
/// Integerをとり、IntegerをとりIntegerをとりIntegerを返す関数を返す
Function<Integer, Function<Integer, Function<Integer, Integer>>> hoge3 = value -> (a -> (b -> value + a + b));
hoge3.apply(1).apply(2).apply(4);   // return 7
// Integerをとり、IntegerをとりIntegerをとりIntegerをとりIntegerを返す関数を返す
Function<Integer, Function<Integer, Function<Integer, Function<Integer, Integer>>>> hoge4 = value -> (a -> (b -> (c -> value + a + b + c)));
hoge4.apply(1).apply(2).apply(4).apply(8);  // return 15

hoge5 ~ 7 は、引数がクロージャのため、事前に処理を渡しておく必要がある
(hoge5 ~ 7 は、引数が関数のため、hoge1 ~ 4 の返却値を使いました)

// IntegerをとりIntegerを返す関数をとり、IntegerをとりIntegerをとりIntegerをとりIntegerを返す関数を返す
Function<Function<Integer, Integer>, Function<Integer, Function<Integer, Function<Integer, Integer>>>> hoge5 = hoge -> (a -> (b -> (c -> hoge.apply(a + b + c))));

hoge5.apply(hoge1).apply(1).apply(2).apply(4);  // return 7
hoge5.apply(hoge2.apply(1)).apply(2).apply(4).apply(8); // return 15
hoge5.apply(hoge3.apply(1).apply(2)).apply(4).apply(8).apply(16);   // return 31
hoge5.apply(hoge4.apply(1).apply(2).apply(4)).apply(8).apply(16).apply(32); // return 63
// IntegerをとりIntegerをとりIntegerを返す関数をとり、IntegerをとりIntegerをとりIntegerをとりIntegerを返す関数を返す
Function<Function<Integer, Function<Integer, Integer>>, Function<Integer, Function<Integer, Function<Integer, Integer>>>> hoge6 = hoge -> (a -> (b -> (c -> hoge.apply(a).apply(b + c))));

hoge6.apply(hoge2).apply(1).apply(2).apply(4);  // return 7
hoge6.apply(hoge3.apply(1)).apply(2).apply(4).apply(8); // return 15
hoge6.apply(hoge4.apply(1).apply(2)).apply(4).apply(8).apply(16);   // return 31
// IntegerをとりIntegerをとりIntegerをとりIntegerを返す関数をとり、IntegerをとりIntegerをとりIntegerをとりIntegerを返す関数を返す
Function<Function<Integer, Function<Integer, Function<Integer, Integer>>>, Function<Integer, Function<Integer, Function<Integer, Integer>>>> hoge7 = hoge -> (a -> (b -> (c -> hoge.apply(a).apply(b).apply(c))));

hoge7.apply(hoge3).apply(1).apply(2).apply(4);  // return 7
hoge7.apply(hoge4.apply(1)).apply(2).apply(4).apply(8); // return 15

返却値である関数をそのまま持つことももちろんできる
数値を渡しているが、実際に計算は行われていない

hoge7.apply(hoge3); // return Function
hoge7.apply(hoge3).apply(1);    // return Function
hoge7.apply(hoge3).apply(1).apply(2);   // return Function

ループを回して、全部足す...
Java8以前ではfor文を使っていた計算もご覧の通り!
そろそろ眠くなってきた...w

int sum = IntStream.rangeClosed(1, 100).sum();    // return 5050

TとTをとりTを返すクロージャをとり、TをとりTをとりTを返すクロージャを返す(また明日でいいや...ww)


ループを回して最大値を得る(stream処理でなんとかしよう...)

最後に

すべてきちんと読んだ方、お疲れ様でした。(最後は力尽きたのでまた次回にします...)
実際のプロダクトには上記のような他人が読みづらいクソコードは埋め込まないように注意しましょう。

関数型プログラミングって慣れないとツライですが、わかるようになってくると楽しいです。
とりあえず、Javaによる関数型プログラミングをやって、すごいH本も読もうと思います。

P.S
Javaのラムダ式ってどこで改行するのがベストなんでしょうか...(・・?)