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