2011-11-06 6 views
8

Mam na myśli "Programowanie w Scala 2ed". W sekcji 24.4 zauważono, że Iterable zawiera wiele metod, których nie można efektywnie napisać bez iteratora. Tabela 24.2 zawiera te metody. Jednak nie rozumiem, dlaczego niektóre z nich nie mogą być skutecznie wdrożone w iteratorze. Na przykład rozważ zipWithIndex.Dlaczego program zipWithIndex został zaimplementowany w programie Iterable i nie można go przetransponować?

def zipWithIndex[A1 >: A, That](implicit bf: CanBuildFrom[Repr, (A1, Int), That]): That = { 
    val b = bf(repr) 
    var i = 0 
    for (x <- this) { 
     b += ((x, i)) 
     i +=1 
    } 
    b.result 
    } 

Dlaczego nie przenieść tej definicji na ruchomy? Wydaje mi się, że kod może być dokładnie taki sam i nie byłoby różnicy w wydajności.

+0

Chciałem tylko dodać przypadek użycia dla '' przesuwny na zipWithIndex' '. Co się stanie, jeśli zastosujesz metodę wybierania losowego elementu z traversalable? Podczas iteracji po elementach potrzebny jest indeks, który pomaga z prawdopodobieństwami, mimo że indeks nie odpowiada trwałej lokalizacji ze strukturą. – schmmd

Odpowiedz

11

Masz całkowitą rację, a Twoja implementacja powinna zadziałać. Nie ma żadnego powodu, aby mieć zipWithIndex zdefiniowany w Iterable, a nie Traversable; ani nie daje żadnej gwarancji co do porządku elementów znajdujących się w ruchu.

(To jest moja pierwsza odpowiedź na StackOverflow. Nadzieja byłem pomocny. :) Jeśli ja nie, proszę mi powiedzieć.)

+0

Całkowicie pomocna, masz +6 za to! Po prostu upewniłem się, że czegoś mi nie brakuje, ponieważ rozdział wyraźnie stwierdza, że ​​metody w tabeli są wdrażane w Iterable, ponieważ są tam łatwiejsze lub bardziej wydajne. – schmmd

10

Traversable nie gwarantuje porządek, w którym elementy będą odwiedzane i tylko wymaga, aby zdefiniować metodę foreach z następującym podpisem:

def foreach[U](f: Elem => U): Unit 

Ponieważ metoda ta po prostu potrzebuje zadzwonić f dla każdego elementu dowolne zamówienie, nie ma sensu posiadanie indeksu na elementach, ponieważ zamówienie może być inne dla każdej inwokacji foreach.

Edytuj: To jest naprawdę tylko wytłumaczenie, dlaczego nie jest dostępne na Traversable. Jak zauważył Luigi w komentarzach, zipWithIndex miałoby więcej sensu na Seq.

+1

Zgadzam się, że indeksy nie są per se znaczące na "Traversable" (rozważmy na przykład wykresy). W szczególności nie będzie można nic zrobić z uzyskanym indeksem * w kolekcji *. Ale możesz chcieć mieć indeks "pętli" dla czegoś innego (i być po prostu naśladować posiadanie 'i' w typowej pętli' for' w stylu Java), więc dlaczego nie? – Raphael

+1

'Iterable' (który zawiera mapy i zestawy) nie gwarantuje kolejności, w której elementy będą odwiedzane. Lepszym pytaniem byłoby pytanie, dlaczego 'zipWithIndex' jest zdefiniowany w' Iterable' zamiast 'Seq'. –

+0

Po tej dyskusji wydaje się, że foreach ma więcej sensu zarówno na Traversable (dlaczego nie) lub Seq (kolejność guarenteed)! – schmmd

Powiązane problemy