2

私はscalaでscalaz 6.0を使用しています。入力ストリームから読み取るために iteratees を使用しています。

私が持っている simple.txt という単純なファイルを次に示します。

これ

テストです

私の iteratee は行を印刷するために io モナドを構築します

def printLines: IterV[String, IO[Unit]] = {
  def step(currentIO: IO[Unit])(input: Input[String]): IterV[String, IO[Unit]] = 
    input match {
      case El(x) => Cont(
          step(
              currentIO.flatMap(_ => putStrLn(x))
          )
      )
      case IterV.Empty() => Cont(step(currentIO))
      case EOF() => Done(currentIO, EOF[String])
    }
  Cont(step(io()))
}

enumeratorM を使用する場合

getFileLines(new File(".../simple.txt"))(printLines).flatMap(_.run).unsafePerformIO

正しい出力を取得します。

使おうとすると

getLines(printLines).flatMap(_.run).unsafePerformIO

「これ」だけがコンソールに返されます。getLines は標準入力ストリームを使用します。iteratee にデバッグ ステートメントを追加しましたが、getLines は最初の行の後に EOF() を送信しているようで、解決できませんでした。

4

1 に答える 1

2

これは の定義のバグですgetReaderLines。現在のバージョンを比較します。

/** Enumerate the lines from a BufferedReader */
def getReaderLines(r: => BufferedReader): EnumeratorM[IO, String] =
  new EnumeratorM[IO, String] {
    def apply[A](it: IterV[String, A]) = {
      def loop(i: IterV[String, A]): IO[IterV[String, A]] = i.fold(
        done = (_,_) => io { i },
        cont = k => for {
          s <- rReadLn(r)
          a <- s.map(l => loop(k(El(l)))).getOrElse(io(i))
        } yield a
      )
      loop(it)
    }
  }

動作するもので:

/** Enumerate the lines from a BufferedReader */
def getReaderLines(r: => BufferedReader): EnumeratorM[IO, String] =
  new EnumeratorM[IO, String] {
    lazy val reader = r

    def apply[A](it: IterV[String, A]) = {
      def loop(i: IterV[String, A]): IO[IterV[String, A]] = i.fold(
        done = (_,_) => io { i },
        cont = k => for {
          s <- rReadLn(reader)
          a <- s.map(l => loop(k(El(l)))).getOrElse(io(i))
        } yield a
      )
      loop(it)
    }
  }

問題は、それrが名前によるパラメーターであることです。つまり、定義されている方法を考えるとgetLines、現在のバージョンでは、すべてのループで標準入力をラップする新しいリーダーが作成されます。

これがライブラリで修正されるまで (そして、6.0.5 を急いでリリースすることはないと思います)、最も簡単な修正は、独自の .xml を作成することgetLinesです。

val getLines: EnumeratorM[IO, String] = {
  val r = new BufferedReader(new InputStreamReader(System.in))
  getReaderLines(r)
}

これは期待どおりに機能します。

于 2013-08-18T02:28:35.820 に答える