如何在进程中断

时间:2015-06-05 19:18:10

标签: scala functional-programming scalaz scalaz-stream

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

我遵循了教程scalaz streams,他们有一个控制台读写的例子。

但我遇到了一个奇怪的问题,我不确定如何理清。

这是我的代码:

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需要输入两次。

问题是当进程失败时控制台输入未被解锁(未被杀死)并且仍在等待用户的输入。

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

谢谢。

1 个答案:

答案 0 :(得分:1)

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

在这个例子中,如果您的处理只是读取一个打印,那么您不需要runLog,因此您想要的只是要处理的任意效果。

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

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

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