SSブログ

引数なしの関数オブジェクト [Scala]

Scala で引数なしの関数オブジェクトを作る場合、基本的には以下のように「 () 」を仮引数の場所に書くことになる。

scala> { () => Console.println("Hello World!") }
unnamed10: () => Unit = <function>

この「() =>」を省いてしまうと関数オブジェクトというよりも単にブロックとして実行されてしまう。

scala> { Console.println("Hello World!") }
Hello World!
unnamed11: Unit = ()

しかしこれを省いてもいい場面というのがあって、それは「() => Unit」型でなく「=> Unit」型として指定されているメソッド引数に渡す場合である(勿論矢印の右辺は Unit でなくても何でもいい)。

scala> def f(g: => Unit) { }
f: (=> Unit)Unit

scala> f { Console.println("Hello World!") }
unnamed14: Unit = ()

Perl で高階関数を書くときにプロトタイプ指定をしてあげると呼ぶときに sub と書かなくてもよくなる、というのにちょっと似ているかもしれない。
それはともかく、これを使って前の記事 [1] の 3.times 構文を書き直すと以下のようになる。

scala> class Loop(n: int) { def times(x: => Unit): Unit = {for (i <- 1 to n) x } }
defined class Loop

scala> implicit def int2loop(n: int): Loop = { new Loop(n) }
int2loop: (int)Loop

scala> 3.times { Console.println("cheer"); }
cheer
cheer
cheer
unnamed15: Unit = ()

このようにこれは DSL っぽいことをするのに重宝する。Scala の Actor ライブラリでもこの型が活用されていて、このおかげであたかも Actor 用の特別な構文があるかのように見える(実際にはただのライブラリであって言語仕様に対する拡張ではない)。

なお型指定のときに「x: => Unit」というようにコロンと矢印の間には空白を挟まなければいけない。「:=>」は Scala の識別子になりうるので空白をはさまない場合はシンタクスエラーになる。

[1] http://blog.so-net.ne.jp/rainyday/2007-05-31


nice!(0)  コメント(0)  トラックバック(0) 
共通テーマ:パソコン・インターネット

nice! 0

コメント 0

コメントを書く

お名前:
URL:
コメント:
画像認証:
下の画像に表示されている文字を入力してください。

トラックバック 0

この広告は前回の更新から一定期間経過したブログに表示されています。更新すると自動で解除されます。