implicit conversions とブロックの組み合わせは失敗する?
java のスレッドを利用せざるを得ないときに、スッキリ記述できるかと思い、以下のように implicit を使ってみたのですがうまくいきませんでした。
object Sample {
implicit def block2Thread(block: => Unit) = new Thread { override def run = block }
def main(args: Array[String]): Unit = {
Runtime.getRuntime().addShutdownHook {
println("foo")
println("bar")
}
println("----")
}
}
アプリケーション終了時に、"foo"と"bar"が出力されることを期待しているのですが、実際には以下のように出力されます。
foo
-
-
- -
-
addShutdownHook に続くブロック全体に implicit def block2Thread が適用されることを期待していたのですが、実際は println("foo") が実行され、println("bar") は値としてブロックから返されているようです。そのため、println("bar") がスレッドの本体として使用されているようです。
ちなみに implicit def による型変換をしていない場合は、期待通りブロック全体が関数の引数として渡されます。詳しい仕様を調べていないので想像ですが、implicit def による型変換は出来る限り後で適用されるようですね。
implicit を駆使すれば、もっと良い方法があるのかも知れませんが現時点では以下のようにすることにしました。
object Sample { def thread(block: => Unit) = new Thread { override def run = block } def main(args: Array[String]): Unit = { Runtime.getRuntime().addShutdownHook(thread { println("foo") println("bar") }) println("----") } }
めでたく、以下のように出力されました。
-
-
- -
-