2013-05-03 75 views
6

我運行下面的代碼:斯卡拉 - 迭代器和takeWhile

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

,並返回(1,1,1)。但是,如果我運行此:

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

我越來越(1,1)。爲什麼會這樣?是否head在致電takeWhile後進行評估,結果應該是相同的?

回答

15

因爲迭代器是可變的,所以it.head的值取決於它的計算時間。

檢查implementation of takeWhile顯示它在應用謂詞之前刪除了迭代器之前的頭部

因此,在第三次迭代時,it.head從謂詞內求值將是2,因爲第三個元素已經被刪除。

這是爲什麼你應該更喜歡不變性的例證。它排除了像這樣的一類非顯而易見的行爲。

0

在上面添加@Ben James答案。下面是takeWhile方法代碼(學分:BEN):

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

在第三次迭代中第2行後,該值是:hd=1和剩餘迭代是List(2,2,3,3)。在調用p(hd)時,它檢查迭代器的head,在本例中爲2。因此它破裂。