2017-11-16 2 views
0

Ich experimentiere mit Reißverschlüssen in Scala und ich habe Schwierigkeiten, benutzerdefinierte Iterator-Funktionen, um mit ihnen zu arbeiten.Zip funktioniert nicht gut mit benutzerdefinierten Iterator-Funktion in Scala

Ich habe den folgenden Beispielcode:

Iterator 
    .continually("s") 
    .zip((1 to 5).iterator) 
    .takeWhile { 
    case ("s", 2) => println("two"); true 
    case ("s", i) => println(i); true 
    } 
    .foreach { f: (String, Int) => 
    println(f) 
    } 

Wenn ich es laufen, es die Ergebnisse ausdruckt Ich erwarte:

1 
(s,1) 
two 
(s,2) 
3 
(s,3) 
4 
(s,4) 
5 
(s,5) 

Allerdings, wenn ich die takeWhile mit meiner benutzerdefinierten tauschen takeDoWhile (Es enthält das letzte fehlerhafte Ergebnis), ich bekomme etwas, was nicht erwartet wird:

1 
(s,1) 
1 
(s,1) 
1 
(s,1) 
1 
(s,1) 
1 
(s,1) 
1 
(s,1) 
... 
(goes on forever) 

Hier ist der Code für die takeDoWhile:

implicit final class InclusiveIterator[A](it: => Iterator[A]){ 
    @inline def takeDoWhile(predicate: A => Boolean): Iterator[A] = new AbstractIterator[A] { 
    private var continue: Boolean = true 

    def hasNext: Boolean = it.hasNext && continue 

    def next(): A = { 
     if(continue){ 
     val result: A = it.next() 
     if (!predicate(result)) continue = false 
     result // Give the result even if the predicate fails, but only once. 
     }else{ 
     empty.next() 
     } 
    } 
    } 
} 

Das Seltsame ist meine takeDoWhile funktioniert so lange völlig in Ordnung, da es keinen Reißverschluss beteiligt ist.

Antwort

0

Dies wird verursacht, Sie verwenden by name parameter: it: => Iterator[A] für InclusiveIterator, und da namentlich Parameter in jeder Zeit eval wird es verwendet.

Da it in takeDoWhile Verfahren wird es reeval es an jedem Ort eingesetzt, so it.next wird die Änderung nicht es Iterators versetzt.

es ein Beispiel ist nach Namen Parametern für eval zu erklären:

def foo(name: => String): Unit = { 
    println(name) 
    println(name) 
    println(name) 
    } 
    foo({println("start"); "end"}) 
    >start 
    >end 
    >start 
    >end 
    >start 
    >end 

Im obigen Beispiel ist die name nach Namen Parametern werden 3-mal in println(name) eval.

Also für Ihre Nutzung, sollten Sie nicht die namentlich Parameter verwenden direkt Parameter als Wert verwenden.

Verwandte Themen