3

次の例は、PlayFrameworkのドキュメントを基にしています。

val enumerateUsers: Enumerator[String] = {
  Enumerator("Guillaume", "Sadek", "Peter", "Erwan")
}
val consumeOne = Cont[String, String](in =>
  in match {
    case Input.EOF =>
      Done("", Input.Empty)
    case Input.Empty =>
      Done("", Input.Empty)
    case Input.El(s) =>
      Done(s, Input.Empty)
  })
println((enumerateUsers |>> consumeOne).flatMap(_.run).await.get)

印刷しGuillaumeます。

ただし、次のように変更するEnumeratorPushEnumerator

val enumerateUsers: PushEnumerator[String] = Enumerator.imperative[String]()
// consumeOne as before
val i = enumerateUsers |>> consumeOne
enumerateUsers.push("Guillaume")
enumerateUsers.push("Sadek")
enumerateUsers.push("Peter")
enumerateUsers.push("Erwan")
println(i.flatMap(_.run).await.get)
// Timeout exception

iterateeの約束でタイムアウト例外が発生します。

以前と同じように動作させるには、を閉じる必要がありPushEnumeratorます。

val enumerateUsers: PushEnumerator[String] = Enumerator.imperative[String]()
// consumeOne as before
val i = enumerateUsers |>> consumeOne
enumerateUsers.push("Guillaume")
enumerateUsers.push("Sadek")
enumerateUsers.push("Peter")
enumerateUsers.push("Erwan")
enumerateUsers.close() // <-- magic line
println(i.flatMap(_.run).await.get)

そして、これは以前と同じように印刷Guillaumeされます。

理由やセマンティックディファレンスがここにあることを教えてくれるドキュメントが見つかりません。誰かが道を教えてもらえますか?

編集:Playソースで私の答えを見つけました-それはいくつかの狩りが必要でした:) @huynhjlの答えはある種の答えなので、正しいとマークしますが、私が探していた具体的な答えは非常に単純です。Playの実装では、副作用を使用してソケットを駆動しますが、これは不合理ではありません。これは、私が想定していたことではありません(想定によりすべてが強制終了されます:D)。中play.core.server.netty.Helpersにはと呼ばれる関数がありますsocketOut[A](...)。 Iterateeを返すsocketOut[A](...)と呼ばれる関数があります。stepこのIterateeはe、入力ケースがに一致すると、出力チャネルに書き込みますEl(e)。私の仮定では、Iterateesは値を取得できる列挙子を部分的に消費する可能性がありますが、それを実現する唯一の方法は副作用によるもののようです...私は:)

4

1 に答える 1

2

オブジェクトの役割はEnumerator、要素がなくなるまで、またはiterateeが完了するまで、特定の順序でiterateeに要素をフィードしてから、そのiterateeを返すことです。このclose()呼び出しは、入力がなくなったことを示し、反復結果を返すことができます。closeを呼び出さなくても、プッシュすることがまだまだある可能性があります。だから私は試していませんが、これはあなたの例と同等になると思います:

val i = enumerateUsers |>> consumeOne
i.flatMap(_.run).onRedeem(println) // we will have a result we want to print
// now feed some data
enumerateUsers.push("Guillaume")
enumerateUsers.push("Sadek")
enumerateUsers.push("Peter")
enumerateUsers.push("Erwan")
// no more input, trigger promise computation
enumerateUsers.close() 

enumerateUsers結果を得るのに必要な要素の数を事前に知ることができない反復子に適用すると、より意味があります(一般的な場合)。

于 2012-05-17T20:55:02.617 に答える