8

我正在运行以下代码:

 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结果应该是一样的吗?

4

2 回答 2

16

因为迭代器是可变的,所以 的值it.head取决于它的计算时间。

检查 的实现takeWhile表明它在应用谓词之前删除了迭代器的头部。

因此,在第三次迭代中,it.head从谓词中评估的将为2,因为第三个元素已被删除。

这说明了为什么您应该更喜欢不变性。它排除了一整类像这样的非显而易见的行为。

于 2013-05-03T10:45:33.303 回答
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。因此它破裂了。

于 2013-05-03T10:54:05.920 回答