Question

I want to write an enumeratee that just pushes one Input.El into the iteratee and then returns the remaining iteratee. I call it prepend, because it changes the stream by just prepending a value to it. Here is my try:

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

When I now call it via

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

it only prints the 0 which should be prepended. The other values from the enumerator are ignored. If I do also override the &> method of the enumeratee (transform method), I can get it working:

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

But that's not a very clean way, because the applyOn method still is invalid. I think I mistakted the meaning of the applyOn method. In my opinion it should return an iteratee that returns the original iteratee and input is continued on the original iteratee then.

The transform method above should explain, what behaviour I want from my enumeratee. How can I achieve this behaviour by overwriting applyOn instead of transform?

Was it helpful?

Solution

Either you edit your prepend Enumeratee to be like the following:

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

Or you get the original Iteratee after applying the Enumeratee and the Enumerator to it, something like Scala: Getting original iteratee after applying enumeratee (example from play documentation doesn't compile)

&>> will end the inside iteratee when the outside is Done. This is the only way to be able to get Iteratee[EOuter,AInner] since Enumeratee are mostly about adapting.

OTHER TIPS

What about

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

or

Enumerator(1,2,3,4) |>> (Enumeratees.prepend2(0) &> Iteratee.foreach[Int]{i=>println(i)})
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top