2013-05-03 73 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。因此它破裂。