Frage

Ich habe den Code unten bearbeitet, da ich glaube, dass ich die ITerv -Objekte falsch über dem kombiniert habe iter.next Ausgabe.

Ich experimentiere mit Iteratee In Scalaz und ich frage mich, warum Folgendes nicht funktioniert. Hier ist was ich habe:

import scalaz._
import Scalaz._
import IterV._

implicit val iteratorEnumerator = new Enumerator[Iterator] {
  def apply[E,A](iter: Iterator[E], i: IterV[E,A]): IterV[E,A] =
    if (iter.isEmpty) i
    else i.fold(done = (acc,input) => i, 
                cont = k => apply(iter, k(El(iter.next))))
}

/* probably incorrect
val iter = Iterator(1,2,3)
println("peek(iter) " + peek(iter).run)
println("peek(iter) " + peek(iter).run)
*/

def peekpeek[E]: IterV[E, (Option[E],Option[E])] = 
  for (a <- peek; b <- peek) yield (a,b)
def peekheadpeek[E]: IterV[E, (Option[E],Option[E],Option[E])] = 
  for (a <- peek; b <- head; c <- peek) yield (a,b,c)

peekpeek(Iterator(1,2,3,4)).run
peekheadpeek(Iterator(1,2,3,4)).run

Dies kehrt zurück:

res0: (Option[Int], Option[Int]) = (Some(1),Some(2)) 
res1: (Option[Int], Option[Int], Option[Int]) = (Some(1),Some(2),Some(3)) 

Wo ich erwartet hatte (Some(1),Some(1)) und (Some(1),Some(1),Some(2)).

Ich vermute, das hat damit zu tun iter.next Seiteneffekt sein. Was ist der beste Weg, um damit umzugehen?

Zum Vergleich, Dies direkt aus den Quellcode -Beispielen aus dem Scalaz genommen Webseite Funktioniert einwandfrei:

implicit val StreamEnumerator = new Enumerator[Stream] {
  def apply[E, A](e: Stream[E], i: IterV[E, A]): IterV[E, A] = e match {
    case Stream() => i
    case x #:: xs => i.fold(done = (_, _) => i, 
                            cont = k => apply(xs, k(El(x))))
  }
}
War es hilfreich?

Lösung

Ich glaube, ich habe das herausgefunden. Es schien in erster Linie zu sein El Verwenden eines Parameters mit Namen, der neu berechnet iter.next - sowie wie ich die Berechnung zunächst falsch mit zwei verschiedenen nannte peek(iter).run. Ich habe den Enumerator neu geschrieben, um zuerst zugewiesen zu werden iter.next zu einem val (und machte es auch im Prozess rekursiv):

implicit val iteratorEnumerator = new Enumerator[Iterator] {
  @annotation.tailrec
  def apply[E,A](iter: Iterator[E], i: IterV[E,A]): IterV[E,A] = i match {
    case _ if iter.isEmpty => i
    case Done(acc, input) => i
    case Cont(k) => 
      val x = iter.next
      apply(iter, k(El(x)))
  }
}

Dann:

def peekpeek[A] = 
  for (a1 <- peek[A]; a2 <- peek[A]) yield (a1,a2)
def peekheadpeek[A] = 
  for (a1 <- peek[A]; a2 <- head[A]; a3 <- peek[A]) yield (a1,a2,a3)
def headpeekhead[A] = 
  for (a1 <- head[A]; a2 <- peek[A]; a3 <- head[A]) yield (a1,a2,a3)

peekpeek(Iterator(1,2,3)).run
peekheadpeek(Iterator(1,2,3)).run
headpeekhead(Iterator(1,2,3)).run
length(Iterator.from(1).take(1000000)).run

würde dies zurückgeben:

res13: (Option[Int], Option[Int]) = (Some(1),Some(1))
res14: (Option[Int], Option[Int], Option[Int]) = (Some(1),Some(1),Some(2))
res15: (Option[Int], Option[Int], Option[Int]) = (Some(1),Some(2),Some(2))
res16: Int = 1000000

Andere Tipps

Sie haben Recht mit iter.next und verursachen Nebenwirkungen. Ich denke, dass die Frage auf den Unterschied zwischen einem Strom und einem Iterator hinausgeht. Diese Frage hat relevante Informationen.

Iteratees sind faul. Nebenwirkungen (Iterator) und Faulheit mischen sich nicht. Vielleicht tut das das Richtige:

implicit val iteratorEnumerator = new Enumerator[Iterator] {
  def apply[E,A](iter: Iterator[E], i: IterV[E,A]): IterV[E,A] =
    iter.foldRight(i)((x, y) =>
      y.fold(done = (acc, input) => y,
             cont = k => apply(iter, k(El(x))))
    )
}

Andererseits, vielleicht auch nicht. Es wird nur die Quelle von FoldRight wissen. Nebenwirkungen sind so.

Sie können Nebenwirkungen vermeiden, indem Sie einen Wegwerf Iterator mit der ersten Größe erstellen:

implicit val iteratorEnumerator = new Enumerator[Iterator] {
  def apply[E,A](iter: Iterator[E], i: IterV[E,A]): IterV[E,A] =
    if (iter.isEmpty) i
    else i.fold(done = (acc,input) => i, 
                cont = k => apply(iter, k(El(iter.take(1).next))))
}
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top