Edited at

Functionで遊ぶJava

この記事は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のラムダ式ってどこで改行するのがベストなんでしょうか...(・・?)