3

嗨,我看到了我认为 scala 中的奇怪行为。在 bufferedIterator 上调用 head 似乎是在增加内部函数中的 head。在这种情况下为什么输出正确,要么我的期望是错误的。还是输出错误?

给定:

import scala.io.Source

val source = Source.fromString("abcdef")

val buff1 = source.buffered;

println("outer head 1: " +buff1.head)
println("outer head 2: " +buff1.head)

def readLine():List[String] = {
  def buffered = source.buffered
  def readLine(tokens:List[String] , partialToken:String):List[String] = {
    println("head1 " + buffered.head)
    println("head2 " + buffered.head)
    return Nil;
  }
  return (readLine(Nil, ""));
}

readLine();

这对我的预期输出是

outer head 1: a
outer head 2: a
head1: a
head2: a

实际输出如下。

outer head 1: a
outer head 2: a
head1 b
head2 c
4

3 回答 3

1

scala.io.Source是并且表现得像一个Iterator[Char]. 因此,您必须确保不要一次在多个地方使用它:在您的示例中Iterator.next从 3 个不同的地方调用 3 次BufferedSource,因此您从中得到不同的值:

  1. buff1.head: 缓冲的源还没有缓冲任何东西,所以在head这里请求next内部源调用,因此是第一个a.
  2. buff1.head再次:这里头部已经被缓冲,所以你得到a并且内部源没有改变。
  3. buffered.head: 因为buffered是 a def,所以这等价于source.buffered.head。这个新的缓冲源还没有缓冲任何东西,所以请求head从内部源中检索一个元素,因此b.
  4. buffered.head:这会创建另一个缓冲源,与上面相同,你会得到c.

底线是:如果你调用source.buffered,永远不要source直接再次使用,也不要多次调用它

您的示例可以通过buffered立即调用来修复:

val source = Source.fromString("abcdef").buffered

您也可以def buffered =转入val buffered =以确保source.buffered不被多次调用。

于 2013-06-09T17:28:18.727 回答
1

在 bufferedIterator 上调用 head 似乎是在增加内部函数中的 head。

注:(2016 年 7 月 3 年后)

提交 11688eb显示:

SI-9691BufferedIterator应该暴露一个headOption

这向BufferedIteratortrait 公开了一个新的 API。
它将迭代器的下一个元素作为Option.

Some(value)如果有下一个值,并且None没有下一个元素,则返回 。

这应该有助于避免任何形式的增量。

于 2016-07-25T11:50:45.877 回答
0

你是对的,除了它增加的不是一个函数,而是一个简单的字段:第 66 行的IndexedSeqLike,你可以使用一些 IDE 调试器自己检查它并逐步执行

于 2013-06-09T17:27:49.890 回答