最近、Monix というScalaの非同期プログラミング用ライブラリを使い始めました。
最初は、最新安定版である v2.3.3
で色々触ってみて「これは使える!楽しい!」となって、v3.x
系の方はどんな感じかなと思いバージョンを上げてみると、メソッド名をはじめ、色々変わりまくっていることに焦りました。その中で Task.apply
の挙動の変更には注意が必要だなと思ったので書いておきます。
v3.x系でのTask.applyの変更
v2.x
系では、以下のコードは非同期処理になっていたと思います。
val task = Task { // Task.apply 1 + 2 }
ところが、v3.x
系ではこの挙動が同期処理に変わるようです。つまり、Task.apply
と Task.eval
は同じ挙動になる。
Task.applyのコードを比較してみる
それでは、v2.x
系と v3.x
系の Task
のコードを比較してみましょう。以下は抜粋です。
Monix v2.3.3
object Task extends TaskInstances { /** Returns a new task that, when executed, will emit the result of * the given function, executed asynchronously. * * @param f is the callback to execute asynchronously */ def apply[A](f: => A): Task[A] = fork(eval(f))
Monix v3.0.0-RC2
object Task extends TaskInstancesLevel1 { /** Lifts the given thunk in the `Task` context, processing it synchronously * when the task gets evaluated. * * This is an alias for: * * {{{ * val thunk = () => 42 * Task.eval(thunk()) * }}} * * WARN: behavior of `Task.apply` has changed since 3.0.0-RC2. * Before the change (during Monix 2.x series), this operation was forcing * a fork, being equivalent to the new [[Task.evalAsync]]. * * Switch to [[Task.evalAsync]] if you wish the old behavior, or combine * [[Task.eval]] with [[Task.executeAsync]]. */ def apply[A](@deprecatedName('f) a: => A): Task[A] = eval(a)
v3.x
系のコメントにこのような記述があります。
WARN: behavior of
Task.apply
has changed since 3.0.0-RC2. Before the change (during Monix 2.x series), this operation was forcing a fork, being equivalent to the new Task.evalAsync.
以下は機械翻訳
警告:Task.applyの動作が3.0.0-RC2以降に変更されました。変更前(Monix 2.xシリーズ中)、この操作は新しいTask.evalAsyncと同等のフォークを強制していました。
つまり、v3.x
系で非同期な Task
を使いたかったら Task.apply
ではなく Task.evalAsync
を使ってねということみたいです。
終わりに
今回の変更を受けて、 今後は Task.apply
ではなく、Task.evalAsync
で非同期なのか Task.eval
で同期なのかを明示的に書いた方が良いのかなと思いました。v3.x
系では他にも Callback
が任意のエラー型を設定できるようになってたりと大きな変更があるみたいですね。