2

我正在使用 Scalaz Stream 库并尝试创建一个简单的控制台应用程序。

我按照教程scalaz 流,他们有一个控制台读写的例子。

但是我遇到了一个奇怪的问题,我不确定如何解决。

这是我的代码:

import scala.concurrent.duration._
import scalaz.concurrent.Task

object StreamApp extends App {

  (new StreamExec).go3
}

class StreamExec {

  def gets: Task[String] = Task {
    scala.io.StdIn.readLine()
  }

  def puts(ln: String, answer: String): Task[Boolean] = Task {
    println(ln)
    ln.contains(answer)
  }

  def go3 {

    import scalaz.stream.Process

    val q = Seq("1", "2", "3") map { case p =>

      println(s"Say $p")

      val in = Process eval gets

      val out = in flatMap { line =>
        Process eval puts(line, p)
      }

      out.runLog.attemptRunFor(5.seconds)
    }

    println(q)
  }
}

当我运行它时,输出看起来像这样

background log: info: Say 1
1
background log: info: 1
background log: info: Say 2
background log: info: Say 3
3
3
background log: info: 3
background log: info: List(\/-(Vector(true)), -\/(java.util.concurrent.TimeoutException), \/-(Vector(true)))

1 很好,2 5 秒后超时失败,然后 3 需要输入两次。

问题是当进程按时失败时,控制台输入没有被解除阻塞(没有被杀死)并且仍在等待用户的输入。

我试图用期货重现它并面临同样的问题。

谢谢你。

4

1 回答 1

1

通常在 scalaz 流中,您获取(获取值)然后处理它并终止。

在此示例中,如果您的处理只是读取打印,则不需要 runLog,因此您想要的只是要处理的任意效果。

我认为这段代码可能会有所帮助

eval(gets)
.flatMap { name =>   Process(1,2,3).flatMap( ln => eval(puts(ln,name))) }
.take(3)
.run.run

您真正需要的是为pipe您的流程选择一个 Process1 组合器,这最终将终止您的程序。您可以尝试各种可用于构建程序的组合器。

于 2015-06-07T06:35:31.717 回答