3

我想写一个 enumeratee,它只将一个 Input.El 推入 iteratee,然后返回剩余的 iteratee。我称它为 prepend,因为它只是通过为其添加一个值来更改流。这是我的尝试:

object Enumeratees {
  def prepend[T](toPrepend: T) = new Enumeratee[T, T] {
    def applyOn[A](inner: Iteratee[T, A]): Iteratee[T, Iteratee[T, A]] = {
      val prepended = Iteratee.flatten(inner.feed(Input.El(toPrepend)))
      Done(prepended, Input.Empty)
    }
  }
}

当我现在通过

Enumerator(1,2,3,4) |>> (Enumeratees.prepend(0)  &>> Iteratee.foreach[Int]{i=>println(i)})

它只打印应该添加的 0 。枚举器中的其他值将被忽略。如果我还覆盖了枚举对象的 &> 方法(转换方法),我可以让它工作:

def prepend[T](toPrepend: T) = new Enumeratee[T, T] {
  def applyOn[A](inner: Iteratee[T, A]): Iteratee[T, Iteratee[T, A]] = {
    val prepended = Iteratee.flatten(inner.feed(Input.El(toPrepend)))
    Done(prepended, Input.Empty)
  }

  override def transform[A](inner: Iteratee[T,A]): Iteratee[T,A] =
    Iteratee.flatten(inner.feed(Input.El(toPrepend)))
}

但这不是一个非常干净的方法,因为 applyOn 方法仍然无效。我想我弄错了 applyOn 方法的含义。在我看来,它应该返回一个返回原始迭代的迭代,然后在原始迭代上继续输入。

上面的转换方法应该解释我想从我的被枚举者那里得到什么行为。如何通过覆盖 applyOn 而不是转换来实现此行为?

4

2 回答 2

7

您可以将 prepend Enumeratee 编辑为如下所示:

object Enumeratees {
  def prepend[T](toPrepend: T) = new Enumeratee[T, T] {
    def applyOn[A](inner: Iteratee[T, A]): Iteratee[T, Iteratee[T, A]] = {
      val prepended = Iteratee.flatten(inner.feed(Input.El(toPrepend)))
      Enumeratee.passAlong[T](prepended)
    }
  }
}

或者你在应用 Enumeratee 和 Enumerator 之后得到原始的 Iteratee,类似于Scala:Getting original iteratee after application enumeratee(play 文档中的示例无法编译)

&>>当外部完成时将结束内部迭代。这是唯一能够获得的方法,Iteratee[EOuter,AInner]因为 Enumeratee 主要是关于适应。

于 2012-06-11T13:35:41.603 回答
0

关于什么

Enumerator(1,2,3,4) |>>
Iteratee.flatten( Enumerator(0) |>> Iteratee.foreach[Int]{i=>println(i)} )

或者

Enumerator(1,2,3,4) |>> (Enumeratees.prepend2(0) &> Iteratee.foreach[Int]{i=>println(i)})
于 2012-06-11T10:28:51.230 回答