【问题标题】:Scala/Play: Write Enumeratee that prepends a value to the streamScala/Play:编写将值添加到流中的 Enumeratee
【发布时间】:2012-06-14 04:19:27
【问题描述】:

我想编写一个枚举器,它只将一个 Input.El 推入迭代器,然后返回剩余的迭代器。我称它为 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 而不是 transform 来实现此行为?

【问题讨论】:

  • 您确定在您的示例中使用的是 &> 而不是 &>>? transform 仅在使用 &>> 时调用。
  • 你是对的。我尝试了两个版本,但都没有工作,但 &>> 应该是正确的。我相应地编辑了问题。

标签: scala playframework playframework-2.0 enumerator iterate


【解决方案1】:

您可以将前置 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 applying enumeratee (example from play documentation doesn't compile)

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

【讨论】:

  • 传递方法有效。谢谢你。是否有一些文档或解释 passAlong 的作用?我在剧本 ScalaDocs 中一无所获。
  • 它是一个 Enumeratee,除了将输入传递给内部 iteratee 之外什么都不做。你是对的,它没有记录(它在 Traversable 下)。
  • 值得注意的是 Enumeratee.headingEnumeratee.trailing 已实现 shortly after this answer(感谢 @Sadache),因此不再需要定义自定义 prepend Enumeratee。
  • 迪伦,感谢您为我节省了大量时间。
【解决方案2】:

怎么样

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)})

【讨论】:

  • 第一种方法行不通,因为我需要枚举对象。在应用于不同的流之前,此枚举对象将与其他枚举对象组合。您的第二种方法与我上面的方法相同,但不起作用。
猜你喜欢
  • 2019-05-28
  • 1970-01-01
  • 2018-11-22
  • 2017-03-04
  • 1970-01-01
  • 1970-01-01
  • 2017-05-16
  • 2016-04-20
  • 1970-01-01
相关资源
最近更新 更多