合并scalaz-stream输入进程似乎在stdin上“等待”

时间:2014-11-18 16:57:43

标签: scala scalaz scalaz-stream

我有一个简单的程序:

import scalaz._
import stream._

object Play extends App {
  val in1 = io.linesR("C:/tmp/as.txt")
  val in2 = io.linesR("C:/tmp/bs.txt")

  val p = (in1 merge in2) to io.stdOutLines
  p.run.run
}

文件as.txt包含五个a,文件bs.txt包含3个b。我看到了这种输出:

a
b
b
a
a
b
a
a
a

但是,当我按如下方式更改in2的声明时:

val in2 = io.stdInLines

然后我得到了我认为的意外行为。根据文档 1 ,程序应根据哪个流更快地提供内容,从每个流中非确定性地提取数据。这应该意味着我看到一堆a被立即打印到控制台,但这根本不会发生。

的确,在我按ENTER之前,没有任何反应。很明显,如果我随机选择一个流来获取下一个元素,那么该行为看起来很像我期望的那样,如果该流阻塞,合并的进程也会阻塞(即使其他流包含数据)。

发生了什么事?

1 - 嗯,好的,文档很少,但 Dan Spiewak his talk中非常清楚地表示它会抓住任何人是第一个提供数据的人

1 个答案:

答案 0 :(得分:6)

问题在于stdInLines的实施。它是阻塞的,它永远不会Task.fork是一个线程。

尝试将stdInLines的实现更改为此实现:

def stdInLines: Process[Task,String] =
    Process.repeatEval(Task.apply { 
    Option(scala.Console.readLine())
    .getOrElse(throw Cause.Terminated(Cause.End))
})

原始io.stdInLines在同一个帖子中运行readLine(),所以它总是在那里等待,直到你输入内容为止。