2011-11-28 24 views
7

Czy ktoś może wyjaśnić, dlaczego te iteratory zachowują się inaczej? Generalnie oczekuję, że ciąg działa jak IndexedSeq[Char]. Czy to jest udokumentowane w dowolnym miejscu?Nieoczekiwane zachowanie iteratora na łańcuchu

val si: Iterator[Char] = "uvwxyz".iterator 
val vi: Iterator[Char] = "uvwxyz".toIndexedSeq.iterator 

val sr = for (i <- 1 to 3) 
      yield si take 2 mkString 
    //sr: scala.collection.immutable.IndexedSeq[String] = Vector(uv, uv, uv) 

val vr = for (i <- 1 to 3) 
      yield vi take 2 mkString 
    //vr: scala.collection.immutable.IndexedSeq[String] = Vector(uv, wx, yz) 
+0

Wydaje się, że '.take (2)' w pierwszym przykładzie tworzy kopię iteratora. – ziggystar

Odpowiedz

7

Nie ma żadnych gwarancji co do stanu iterator po wywołaniu take na nim.

Problem z iteratorami polega na tym, że wiele użytecznych operacji może zostać zaimplementowanych tylko poprzez wywołanie efektów ubocznych. Wszystkie te operacje mają określony bezpośredni efekt, ale mogą również powodować skutki uboczne, których nie można określić (lub skomplikowałyby implementację).

W przypadku take istnieją implementacje, które klonują stan wewnętrzny iteratora i inne, które przesuwają iterator. Jeśli chcesz zagwarantować brak efektów ubocznych, będziesz musiał użyć niezmiennych struktur danych, w każdym innym przypadku twój kod powinien polegać wyłącznie na efektach bezpośrednich.

+0

Hmm, zastanawiam się, dlaczego coś tak ważnego dla tego, czym jest "Iterator", byłoby nieokreślone? –

+0

Zaktualizowałem odpowiedź, aby lepiej podkreślić problem. – Moritz

+2

@LuigiPlinge, na stronie http://www.scala-lang.org/archives/downloads/distrib/files/nightly/docs/library/index.html#scala.collection pojawiły się pewne ulepszenia. Efekt: zobacz po " Rozważ ten przykład dla bezpiecznego i niebezpiecznego użycia ". – huynhjl

Powiązane problemy