【问题标题】:surprising behavior in scala when using iterator over characters in file对文件中的字符使用迭代器时,scala 中的令人惊讶的行为
【发布时间】:2023-03-14 23:15:01
【问题描述】:

在迭代文本文件的字符时,我遇到了一些不一致的行为。

以下脚本

import io.Source
val source = Source.fromFile("blah")
val iter = source.buffered
iter.dropWhile(_.isWhitespace)
for( c <- iter ) {
    println("""char="%c", byte=%d, isWhitespace=%b""".format(c, c.toByte, c.isWhitespace))
}
source.close()

读取以下文件(以 3 个空格开头,然后是 'a' 和第二行文本)

   a
bc de

输出以下内容

char=" ", byte=32, isWhitespace=true
char=" ", byte=32, isWhitespace=true
char=" ", byte=32, isWhitespace=true
char="a", byte=97, isWhitespace=false
char="
", byte=10, isWhitespace=true
char="b", byte=98, isWhitespace=false
char="c", byte=99, isWhitespace=false
char=" ", byte=32, isWhitespace=true
char="d", byte=100, isWhitespace=false
char="e", byte=101, isWhitespace=false
char="
", byte=10, isWhitespace=true

dropWhile(_.isWhitespace) 没有删除这 3 个空格,但在之后的 for 循环中迭代时,c.isWhitespace 返回 true。

有人可以帮我解释一下吗?我在十六进制编辑器中打开了文本文件,对我来说它看起来不错(纯 ascii,没有 UTF 的东西)。

编辑:在 Ubuntu 上使用 Scala 2.9.2

EDIT2:现在我很困惑。以下内容来自 Windows 7 上的 REPL:

c:\projects\scratch>scala
Welcome to Scala version 2.10.2 (Java HotSpot(TM) 64-Bit Server VM, Java 1.7.0_21).
Type in expressions to have them evaluated.
Type :help for more information.

scala> val it = Iterator("a", "b", "cde", "f")
it: Iterator[String] = non-empty iterator

scala> val it2 = it.dropWhile(_.length < 2)
it2: Iterator[String] = non-empty iterator

scala> println(it.next)
cde

scala> println(it2.next)
f

将这段确切的代码作为脚本运行会产生原始问题的行为(dropWhile 未修改迭代器)。

【问题讨论】:

  • 顺便说一句,我已经尝试了你的代码并得到了预期的结果:'a'、'\n'、'b'、...我使用的是 OSX 和 scala 2.10.2
  • 我在 Ubuntu 2.9.2 和 Windows 2.10.2 上得到了描述的行为。我很困惑。我通过引入一个包装迭代器的类(存储为var)来“修复”我的具体问题。现在没关系,虽然我在 Scala 中似乎还有很多东西要学。
  • 我不认为这是关于 scala 的知识。似乎这是一个错误(就像你在 REPL/as 脚本中尝试执行最后一个 sn-p 时得到不同的结果一样)。如果我的怀疑是合法的,我会重新检查并提交错误。

标签: scala


【解决方案1】:

在 scala 中,val 是不可变的对象。一旦设置了 val,就无法更改。当您调用iter.dropWhile(_.isWhitespace) 时,会创建一个新对象,但不会存储在任何地方。如果你想去掉空格,你应该将iter.dropWhile(_.isWhitespace)分配给一个新的val,并在for表达式中调用这个新的val。

【讨论】:

  • 我需要 15 的声望才能投票,所以我忽略了“避免像 +1 或谢谢这样的 cmets”说:谢谢!
  • @AndrewJones,只是一些澄清:vals 不是不可变的对象,而是不可变的引用。 val 引用的对象可以修改,但不能指向另一个对象。
  • 我还是有点困惑。我得到val 和不可变的东西,并将dropWhile 的结果分配给一个新的val 并对其进行迭代产生预期的结果(3 个空格消失了)。然而,以下页面包含dropWhile 的示例(对我而言)似乎与此相矛盾:scala-lang.org/docu/files/collections-api/collections_43.html
  • “矛盾”我的意思是:我已经在 REPL 中尝试过了,并且迭代器在 dropWhile 调用之后改变了内容(没有我绑定返回值)。
  • 但这种行为似乎只存在于 REPL 中。
猜你喜欢
  • 2012-07-27
  • 2021-08-20
  • 2019-10-05
  • 1970-01-01
  • 1970-01-01
  • 2016-12-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多