結構前にりらっくみゃーさんが書いたやつをJavaで書き直してみた。
2chで"解説してくれ"的なことが話題になってて、最初解説を書こうかとおもったんだけど、なんかJava知ってる人にとっては、Javaで書き直してしまったほうが速いのではないかとおもったので
それと、scalaで、戻り値や型引数を省略せずに書き、解説を入れたVersionも(・ω・)ノ
ただ、ちょっと力尽きたので、"イ"の式についてしか解説してないが(・_・`)
// "侵略"という型引数を取るクラス // "侵略"型の"ピコピコ"という名前のオブジェクトをコンストラクタの引数として持つ class イカ言語 [侵略](ピコピコ:侵略){ // "の、に、を"の3つのメソッドは、すべて同じメソッド // 侵略型を引数にとりイカスミ型を返す触手という関数オブジェクトを引数に取り、 // 触手に対して、コンストラクタで受け取ったピコピコを適用した結果を返す。 //戻り値の型はイカスミ def の[イカスミ](触手:(侵略)=>イカスミ):イカスミ = 触手(ピコピコ) def に[イカスミ](触手:(侵略)=>イカスミ):イカスミ = 触手(ピコピコ) def を[イカスミ](触手:(侵略)=>イカスミ):イカスミ = 触手(ピコピコ) } // "祝"というStringのパラメータをとり、受け取ったパラメータの前に"イカスミ"というStringを連結させて、Stringを返す関数 def 料理(祝:String):String = "イカスミ" + 祝 // "侵略"という仮引数名。受け取ったIntをそのまま返す def 計算(侵略:Int):Int = 侵略 // 受け取ったIntを2倍にして、Intを返す関数 def 倍(イカ:Int):Int = イカ * 2 // 仮引数である、"娘"は、"でゲソ"型であるとされているが、この場合つまりでゲソ型はなんでもよい // def しなイカ(娘:Any):String = 娘.toString + "でゲソ" と実際は等価 def しなイカ[でゲソ](娘:でゲソ):String = 娘 + "でゲソ" // "しなイカ" メソッドと全く同じ動作 def 作らなイカ[でゲソ](二期:でゲソ):String = 二期 + "でゲソ" val イ = (new イカ言語[Int]( new イカ言語[Int]( 1 + 1 ).の[Int]( 計算 ) ) ).を[String]( しなイカ )
1 まず型引数Intの"イカ言語"クラスのインスタンスを、(1 + 1)の結果をコンストラクタの引数として渡して作成
new イカ言語[Int]( 1 + 1 )
2 そうして作成したインスタンスの、"の"という名前のメソッドに、"計算"という関数を引数としてわたす
new イカ言語[Int]( 1 + 1 ).の[Int]( 計算 )
3 すると、"計算"という関数は、受け取った引数である"侵略"というIntのパラメータをそのまま返す関数であるので
new イカ言語[Int]( 1 + 1 ).の[Int]( 計算 )
という部分はIntの2になる
4 その2を"イカ言語"のコンストラクタに渡してインスタンス生成
new イカ言語[Int]( 2 )
5 そのインスタンスの"を"というメソッドにたいして、"しなイカ"というパラメータを渡して呼び出す
(new イカ言語[Int]( 2 ) ).を[String]( しなイカ )
6 "しなイカ"により、
2 + "でゲソ"
という計算が行われ、最終的に全体として"2でゲソ"という結果になる
追記
まったく意味が無いが、なんとなくC#が書きたくなったので、C#でも書いてみた。
Javaに比べれば(無名クラスとか生成せずそのまま渡せるので)呼び出す部分が、すごくすっきりしますよね