Scala/Play: Write Enumeratee, который добавляет значение в поток

Я хочу написать 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, которые должны быть добавлены. Остальные значения из счетчика игнорируются. Если я также переопределяю метод & > метода enumeratee (метод преобразования), я могу заставить его работать:

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 вместо преобразования?

Ответ 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)
    }
  }
}

Или вы получаете исходный Iteratee после применения Enumeratee и Enumerator к нему, что-то вроде Scala: получение оригинала iteratee после применения enumeratee (пример из игровой документации не компилируется )

&>> закончит внутреннюю итерацию, когда наружу будет выполнено. Это единственный способ получить Iteratee[EOuter,AInner], поскольку 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)})