引数なしのクロージャ
について・・・
上記Blogの前日記事への
みずしまさんのコメント
=> TypeName
はメソッドの引数専用の修飾子のようなもので、引数が名前渡し(call-by-name)であることを指定するものです。実装的には関数を作って渡してるわけですが、概念的には引数を評価しないまま関数に渡して、関数内部で必要になるたびに評価するイメージですね。引数無しの関数の場合、
() => TypeName
とすることになりますが、こっちの方はあまり使わない気がしますね。
を受けて実験してみた。
scala> val f: => Any = {"s"} <console>:1: error: identifier expected but '=>' found. val f: => Any = {"s"} ^
と、こうなってしまうのを・・・以下のように
scala> val f:() => Any = {"s"} <console>:4: error: type mismatch; found : java.lang.String("s") required: () => Any val f:() => Any = {"s"} ^
としてみたけどまだダメで・・・結局
scala> val f:() => Any = {() => "s"} f: () => Any = <function>
とすれば、
scala> f res0: () => Any = <function> scala> f() res1: Any = s
のようにうまくいった。
で、ここでさらに・・・
scala> var n = 5 n: Int = 5
の時
scala> def f1 = { "s" * n } f1: String
とすれば、もちろん
scala> f1 res15: String = sssss
となるし、これを
scala> def f2 = f1 f2: String
こうしても、もちろん
scala> f2 res16: String = sssss scala> n = 8 n: Int = 8 scala> f2 res18: String = ssssssss
となる。
ここで、おもむろに、
scala> val f3 = f1 f3: String = ssssssss
などとした場合は、
scala> n = 2 n: Int = 2
としても、残念ながら
scala> f3 res20: String = ssssssss
となってしまうので、関数【オブジェクト】として変数に入れたい場合には
scala> val f4 = f1 _ f4: () => String = <function>
とする。
ちなみに、呼び出す時には
scala> f4 res23: () => String = <function>
ではなく
scala> f4() res24: String = ss
となる。
最終的に
scala> n = 20 n: Int = 20
の場合には、
scala> f1 res26: String = ssssssssssssssssssss scala> f2 res27: String = ssssssssssssssssssss scala> f3 res28: String = ssssssss scala> f4() res30: String = ssssssssssssssssssss
となる。