次の例は、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
ます。
ただし、次のように変更するEnumerator
と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")
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は値を取得できる列挙子を部分的に消費する可能性がありますが、それを実現する唯一の方法は副作用によるもののようです...私は:)