2011-11-06 16 views
8

Sto leggendo "Programmazione in Scala 2ed". Nella sezione 24.4, si fa notare che Iterable contiene molti metodi che non possono essere scritti in modo efficiente senza un iteratore. La Tabella 24.2 contiene questi metodi. Tuttavia, non capisco perché alcuni di essi non possono essere implementati in modo efficiente su iteratore. Ad esempio, considera zipWithIndex.Perché zipWithIndex è implementato in Iterable e non Traversable?

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 
    } 

Perché non spostare questa definizione su attraversabile? Mi sembra che il codice potrebbe essere esattamente lo stesso e non ci sarebbe alcuna differenza in termini di efficienza.

+0

Volevo solo aggiungere un caso d'uso per '' zipWithIndex' su Traversable '. Cosa succede se si sta implementando un metodo per scegliere un elemento casuale da un attraversabile? Durante l'iterazione degli elementi, è necessario un indice per aiutare con le probabilità, anche se l'indice non corrisponde a una posizione persistente all'interno della struttura. – schmmd

risposta

11

Sei completamente corretto e la tua implementazione dovrebbe funzionare. Nessuna buona ragione per avere zipWithIndex definito in Iterable e non Traversable; non fornisce alcuna garanzia circa l'ordine degli elementi in attraversamento.

(Questa è la mia prima risposta su StackOverflow. Speranza Sono stato utile. :) Se ho non, mi dica.)

+0

Totalmente utile, hai +6 per quello! Mi sto solo assicurando che non mi manchi qualcosa perché il capitolo afferma chiaramente che i metodi nella tabella sono implementati in Iterable perché sono più facili o più efficienti. – schmmd

10

Traversable non garantisce l'ordine in cui saranno visitati gli elementi e richiede solo di definire un metodo foreach con la seguente firma:

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

Poiché questo metodo ha solo bisogno di chiamare f per ogni elemento in qualsiasi ordine, non ha senso avere un indice sugli elementi poiché l'ordine potrebbe essere diverso per ogni invocazione di foreach.

Modifica: Questa è davvero solo una spiegazione, perché non è su Traversable. Come Luigi ha sottolineato nei commenti, zipWithIndex avrebbe più senso su Seq.

+1

Sono d'accordo sul fatto che gli indici non sono di per sé significativi su un 'Traversable' (si consideri per esempio i grafici). In particolare, non sarà possibile fare nulla con l'indice * ottenuto sulla raccolta *. Ma si potrebbe desiderare di avere l'indice "loop" per qualcos'altro (ed essere giusto per imitare l'uso di 'i' in un tipico' for' loop in stile Java), quindi perché no? – Raphael

+1

'Iterable' (che include mappe e set) non garantisce l'ordine in cui gli elementi saranno visitati. Una domanda migliore potrebbe chiedere perché 'zipWithIndex' è definito su' Iterable' piuttosto che 'Seq'. –

+0

Dopo questa discussione, sembra che foreach abbia più senso su Traversable (perché no) o Seq (ordine garantito)! – schmmd

Problemi correlati