0

TaskLocal の ScalaDoc にあるコード スニペットをわずかに変更したコード ブロックがあります [オリジナルはこちら: https://monix.io/api/3.0/monix/eval/TaskLocal.html ]。

私のコードは、インライン タスク (for 内包表記内) を、for 内包表記の範囲外で定義された Task への参照に置き換えるだけです。残念ながら、私のタスクを実行すると、バインディングは表示されず、代わりに元の値 (0) が表示されます。少し変更したコード (以下) が ScalaDoc のスニペットと同じ結果になることを期待していました。しかし、予期せず、value3: 200 ではなく、"value3: 4" を取得します。tlocal への参照は、デフォルトに初期化され、バインディングについて何も知らない、そのスレッドローカルっぽい変数の別の「バージョン」を取得しているようです。 .

コード

class MonixTests extends FlatSpecLike with Matchers {

  "TaskLocal" should "not make me sad " in {
    val tlocal: Task[TaskLocal[Int]] = TaskLocal(0)

    val readTask: Task[Int] =
      tlocal.flatMap {
        taskLocal: TaskLocal[Int] =>
          taskLocal.read.map{ i => i  * 2 }
      }


    val task: Task[Unit] =
      for {
        local <- tlocal
        value1 <- local.read // value1 == 0
        _ <- local.write(100)
        value2 <- local.read // value2 == 100
        value3 <- local.bind(200)(readTask)
        value4 <- local.read // value4 == 100
        _ <- local.clear
        value5 <- local.read // value5 == 0
      } yield {
        // Should print 0, 100, 400, 100, 0 -- but value3 is not 400, but 4
        println("value1: " + value1)
        println("value2: " + value2)
        println("value3: " + value3)
        println("value4: " + value4)
        println("value5: " + value5)
      }

    import monix.execution.Scheduler.Implicits.global
    implicit val opts = Task.defaultOptions.enableLocalContextPropagation
    task.runToFutureOpt

    println("    TRY AGAIN a slightly different way, but no success ;^( ")

    val task3: Task[Unit] =
      for {
        local <- tlocal
        value1 <- local.read // value1 == 0
        _ <- local.write(100)
        value2 <- local.read // value2 == 100
        value3 <- local.bind(200)(readTask)
        value44 <-  local.bind(200) (
          tlocal.flatMap {
            taskLocal: TaskLocal[Int] =>
              taskLocal.read.map{i => i  *  2}
          }
        )
        _ <- local.clear
        value5 <- local.read // value5 == 0
      } yield {
        // Should print 0, 100, 400, 100, 0 -- but value3 is not 400, but 4
        println("value1: " + value1)
        println("value2: " + value2)
        println("value3: " + value3)
        println("value4: " + value44)
        println("value5: " + value5)
      }

    task3.runToFutureOpt
  }

根拠:

これを行う理由は、値を自分のスレッド ローカルにバインドし、タスクのマップ チェーンを作成して、これらのタスクの一部がスレッド ローカルの現在の値を取得するためです。そして、明確にするために、これらのタスクのいくつかは、私のコードベースの他のクラスで定義されており、理解のために特定の範囲内にインライン化されていません。

ありがとう !/クリス

4

1 に答える 1