2010-01-25 10 views

Odpowiedz

26

można rozszerzyć Iterator, które będą wymagać wdrożenia next i hasNext metody:

class MyAnswer extends Iterator[Int] { 
    def hasNext = true 
    def next = 42 
    } 

Ale, dostaniesz większą elastyczność jeśli przedłużyć Iterable, który wymaga wdrożenia elements (lub iterator w 2,8):

class MyAnswer extends Iterable[Int] { 
    def iterator = new Iterator[Int] { 
     def hasNext = true 
     def next = 42 
    } 
    } 

wspólne idiom wydaje się, aby odsłonić iterator do jakiejś prywatnej kolekcji, na przykład:

class MyStooges extends Iterable[String] { 
    private val stooges = List("Moe", "Larry", "Curly") 
    def iterator = stooges.iterator 
    } 
+0

Nie ma sposobu na wysyłanie prywatnych wiadomości, ale chciałbym zadać pytanie: czy mógłbyś wskazać mi na użycie wspólnego idiomu, o którym wspomniałeś? Jeśli nie, jakie może być przydatne? Dlaczego nie po prostu zwrócić listę? Czy ten idiom nie byłby mniej skuteczny? (Również: widziałem tę sztuczkę Iterable [A] "kilka razy" i wydaje się, że jest to jeden z najszybszych sposobów na stworzenie czegoś podobnego do kolekcji, czy są jakieś "alternatywy" do tego podejścia? Tak, ponieważ Iterator daje mało informacji, więc metod nie można zoptymalizować dobrze, co jeśli wiedziałbym, że mój pseudo coll zwraca zamówione lub ma szybki losowy dostęp) – Aktau

7

na sposób, po prostu yield:

def odd(from: Int, to: Int): List[Int] = 
    for (i <- List.range(from, to) if i % 2 == 1) yield i 
+4

Prawidłowo, ale ... przykład kodu faktycznie nie odpowiada na pytanie. Po prostu zamień oba wystąpienia "List" na "Iterator" i działa idealnie! –

0

Te dwie odpowiedzi miał pomocy z poniższych stanowisk i dzięki @Dima.

Załóżmy, że masz listę klasy powiązane. Wymagane jest wydrukowanie wszystkich elementów na liście.

trait LinkedList { 
    def nodeValue: Int 
    def tailList: LinkedList 
} 

class Node(val nodeValue: Int, val tailList: LinkedList) extends LinkedList 

object Nil extends LinkedList { 
    def nodeValue = throw new IllegalAccessException("head of Nil") 
    def tailList = throw new IllegalAccessException("tail of Nil") 
} 

val singleLinkedList = new Node(1,Nil) 
val chainedLinkedList = new Node(2,singleLinkedList) 
print(chainedLinkedList) 
[email protected]: Unit =() 

Teraz pozwala na wdrożenie iteratora dla tej klasy.

trait LinkedList extends Iterator[Int]{ 
    def nodeValue: Int 
    def tailList: LinkedList 
} 

class Node(val nodeValue: Int, val tailList: LinkedList) extends LinkedList { 
    var ptr: LinkedList = this 

    //The following two are mandatory for extending Iterator 
    override def hasNext: Boolean = ptr match { case Nil => false; case _=> true} 

    override def next(): Int = { 
    val result = ptr.nodeValue 
    ptr = ptr.tailList 
    result 
    } 
} 

object Nil extends LinkedList { 
    def nodeValue = throw new IllegalAccessException("head of Nil") 
    def tailList = throw new IllegalAccessException("tail of Nil") 

    //The following two are mandatory for extending Iterator 
    override def hasNext: Boolean = false 
    override def next(): Int = throw new IllegalAccessException("next of Nil") 
} 

val singleLinkedList = new Node(1,Nil) 
val chainedLinkedList = new Node(2,singleLinkedList) 

//Printing this first Time 
chainedLinkedList.foreach(println) 
//Prints 2 1 

//Printing second Time 
chainedLinkedList.foreach(println) 
//No output 

W implementacji iteratora, gdy ptr osiągnie koniec, może nie wrócić z powrotem. Iterowalna implementacja rozwiązuje to.

trait LinkedList extends Iterable[Int]{ 
    val nodeValue: Int 
    val tailList: LinkedList 
    override def toString(): String = this.mkString(" -> ") 
} 

class Node(val nodeValue: Int, val tailList: LinkedList) extends LinkedList { 

    override def iterator: Iterator[Int] = Iterator 
    .iterate(this: LinkedList)(_.tailList) 
    .takeWhile(_ != Nil) 
    .map(_.nodeValue) 
} 

object Nil extends LinkedList { 
    lazy val nodeValue= throw new IllegalAccessException("head of Nil") 
    lazy val tailList = throw new IllegalAccessException("tail of Nil") 

    override def iterator: Iterator[Int] = Iterator.empty 
} 

val singleLinkedList = new Node(1,Nil) 
val chainedLinkedList = new Node(2,singleLinkedList) 

//Printing this first Time 
chainedLinkedList.foreach(println) 
Output 2 -> 1 
chainedLinkedList.foreach(println) 
Output 2 -> 1