2013-05-03 19 views
6

Sono in esecuzione il seguente pezzo di codice:Scala - iteratori e TakeWhile

val it = List(1,1,1,2,2,3,3).iterator.buffered 
val compare = it.head 
it.takeWhile(_ == compare).toList 

e restituisce (1,1,1). Tuttavia, se eseguo questo come:

val it = List(1,1,1,2,2,3,3).iterator.buffered 
it.takeWhile(_ == it.head).toList 

Sto ottenendo (1,1). Perché è così? Non è stato valutato head al numero takeWhile e il risultato dovrebbe essere lo stesso?

risposta

15

Poiché l'iteratore è mutabile, il valore di it.head dipende da quando viene valutato.

L'ispezione di implementation of takeWhile rivela che rimuove la testa dell'iteratore prima del applicando il predicato.

Quindi, nella terza iterazione, it.head valutata all'interno del predicato sarà 2, perché il terzo elemento è già stato rimosso.

Questa è un'illustrazione del perché si dovrebbe preferire l'immutabilità. Regola un'intera classe di comportamenti non ovvi come questo.

0

Aggiungendo a @ Ben James risposta sopra. Sotto è takeWhile codice metodo (crediti BEN):

def hasNext = hdDefined || tail.hasNext && { 
    hd = tail.next() //line 2 
    if (p(hd)) hdDefined = true 
    else tail = Iterator.empty 
    hdDefined 
} 

Nella terza iterazione dopo la linea 2, il valore è: hd=1 e rimanendo Iterator è List(2,2,3,3). chiamando il numero p(hd), controlla l'iteratore head che in questo caso è 2. Quindi si rompe.