Przyjrzałem się temu pytaniu, ale nadal nie rozumiem różnicy między cechami iterowalnymi i przemiennymi. Czy ktoś może wyjaśnić?
Przyjrzałem się temu pytaniu, ale nadal nie rozumiem różnicy między cechami iterowalnymi i przemiennymi. Czy ktoś może wyjaśnić?
Odpowiedzi:
Mówiąc prościej, iteratory zachowują stan, a trawersable nie.
TraversableMa jeden abstrakcyjny sposób: foreach. Kiedy wywołasz foreach, kolekcja dostarczy przekazanej funkcji wszystkie elementy, które przechowuje, jeden po drugim.
Z drugiej strony Iterablemetoda ma as abstrakcyjną iterator, która zwraca Iterator. Możesz wezwać nexta, Iteratoraby uzyskać następny element w wybranym przez siebie momencie. Dopóki tego nie zrobisz, musi śledzić, gdzie był w kolekcji i co dalej.
Iterablerozciąga się Traversable, więc myślę, że masz na myśli, Traversableże nie są Iterable.
Traversableinterfejsem nie wymaga utrzymywania stanu, podczas gdy zgodność z Iteratorinterfejsem wymaga.
Traversablete, które są Iterable, nie zachowują żadnego stanu iteracji. To Iteratorstworzone i zwrócone przez to, Iterableco utrzymuje stan.
Potraktuj to jako różnicę między dmuchaniem a ssaniem.
Kiedy wywołasz a Traversables foreachlub metody pochodne, będzie on wysyłał wartości do Twojej funkcji pojedynczo - dzięki czemu będzie miał kontrolę nad iteracją.
Z Iteratorpowrotem przez Iterablejednak wysysasz z niego wartości, kontrolując, kiedy samemu przejść do następnej.
tl; dr Iterables są, Traversablesktóre mogą generować stanoweIterators
Po pierwsze, wiedz, że Iterableto jest cecha Traversable.
Druga,
Traversablewymaga implementacji foreachmetody, która jest używana przez wszystko inne.
Iterablewymaga implementacji iteratormetody, która jest używana przez wszystko inne.
Na przykład implementacja findfor Traversableuse foreach(za pomocą a for compearing) i zgłasza BreakControlwyjątek, aby zatrzymać iterację po znalezieniu zadowalającego elementu.
trait TravserableLike {
def find(p: A => Boolean): Option[A] = {
var result: Option[A] = None
breakable {
for (x <- this)
if (p(x)) { result = Some(x); break }
}
result
}
}
W przeciwieństwie do tego, Iterableodejmowania nadpisuje to wdrożenie i rozmów findw sprawie Iterator, która po prostu przestaje iteracji po znalezieniu element:
trait Iterable {
override /*TraversableLike*/ def find(p: A => Boolean): Option[A] =
iterator.find(p)
}
trait Iterator {
def find(p: A => Boolean): Option[A] = {
var res: Option[A] = None
while (res.isEmpty && hasNext) {
val e = next()
if (p(e)) res = Some(e)
}
res
}
}
Byłoby miło nie rzucać wyjątków dla Traversableiteracji, ale to jedyny sposób na częściowe iterowanie, gdy używasz just foreach.
Z jednej perspektywy Iterablejest bardziej wymagającą / potężną cechą, ponieważ można ją łatwo wdrożyć foreachza pomocą iterator, ale tak naprawdę nie można zaimplementować iteratorza pomocą foreach.
Podsumowując, Iterablezapewnia sposób na wstrzymanie, wznowienie lub zatrzymanie iteracji za pomocą stanu Iterator. Z Traversable, to wszystko albo nic (bez wyjątków kontroli przepływu).
W większości przypadków nie ma to znaczenia, a będziesz chciał mieć bardziej ogólny interfejs. Ale jeśli kiedykolwiek będziesz potrzebować bardziej spersonalizowanej kontroli nad iteracją, będziesz potrzebować pliku Iterator, który możesz pobrać z pliku Iterable.
Odpowiedź Daniela brzmi dobrze. Zobaczmy, czy potrafię ująć to własnymi słowami.
Tak więc Iterable może dać ci iterator, który pozwala przechodzić elementy jeden po drugim (przy użyciu next ()) i zatrzymywać się i kontynuować, jak chcesz. Aby to zrobić, iterator musi utrzymywać wewnętrzny „wskaźnik” na pozycję elementu. Ale Traversable daje ci metodę, dla każdego, do przechodzenia przez wszystkie elementy naraz bez zatrzymywania się.
Coś w rodzaju Range (1, 10) musi mieć tylko 2 liczby całkowite jako stan jako Traversable. Ale Range (1, 10) jako Iterable daje iterator, który musi użyć 3 liczb całkowitych dla stanu, z których jedna jest indeksem.
Biorąc pod uwagę, że Traversable oferuje również foldLeft, foldRight, jego foreach musi przejść przez elementy w znanej i ustalonej kolejności. Dlatego można zaimplementować iterator dla Traversable. Np. Def iterator = toList.iterator
Traversablew Scali 2.13 (jest nadal przechowywany jako przestarzały aliasIterabledo 2.14)