Scala 单元类型
Posted
技术标签:
【中文标题】Scala 单元类型【英文标题】:Scala Unit type 【发布时间】:2011-03-05 00:25:08 【问题描述】:我使用opencsv解析csv文件,我的代码是
while( (line = reader.readNext()) != null ) ....
我收到一个编译器警告:
comparing values of types Unit and Null using `!=' will always yield true
[warn] while( (aLine = reader.readNext()) != null )
while循环应该怎么做?
【问题讨论】:
【参考方案1】:在 Scala 中,赋值表达式的类型为 Unit
。这就是您的编译器警告的原因。
Scala 中有一个很好的习惯用法可以避免 while 循环:
val iterator = Iterator.continually(reader.readNext()).takeWhile(_ != null)
这为您提供了一个迭代器,可以遍历 reader.readNext
返回的任何内容。
continually
方法返回一个“无限”迭代器,takeWhile
采用它的前缀,直到但不包括第一个 null。
(Scala 2.8)
【讨论】:
嗯。我的回答与问题不符。我会保留它,无论如何它可能会有用。 为什么你认为你的答案与问题不匹配? @Ken:portoalet 要求解释有关 Unit 的警告。我用循环成语回答。我刚刚添加了警告的解释以使答案完整。 感谢您的澄清。我试图弄清楚你的代码没有做的事情和他的while循环一样。由于它做同样的事情,你的答案与问题不匹配的原因是它没有谈论警告。 值得指出的是,这个Iterator
不会急切地求值,不像while
块会急切地执行?【参考方案2】:
在您的情况下 (line = reader.readNext()) 是返回类型 Unit 的函数文字。你可以重写代码如下:
while( line = reader.readNext(); line!= null ) ....
【讨论】:
请不要接受这个答案:虽然它不是惯用的 Scala,但有更好的方法来实现你想要的(请参阅下面的答案) @oxbow_lakes,也许你在这里有点严厉?核心团队在 2.8 标准库中使用了数百次 while 关键字,这个答案高效、简洁,最重要的是,看起来也像我的答案;@)) 我支持评论,恐怕。这不是惯用的。它甚至没有比 functional 答案更高的性能,因为您的代码将被编译为函数(即对象)实例化【参考方案3】:您可以使用Stream
来获得您想要的:
Stream.continually(reader.readLine()).takeWhile( _ ne null) foreach line =>
//do Stuff
这也有其他很酷的东西的额外优势:
Stream.continually(reader.readLine()).takeWhile( _ ne null) match
case head #:: tail => //perhaps you need to do stuff with the first element?
case _ => //empty
编辑 - 感谢 mkneissl 指出我应该包含这个警告:
scala> Stream.continually(1).take(100000000).foreach(x=>())
scala> val s = Stream.continually(1).take(100000000)
s: scala.collection.immutable.Stream[Int] = Stream(1, ?)
scala> s.foreach(x=>()) java.lang.OutOfMemoryError: Java heap space
【讨论】:
您可能需要添加一个警告,不要保留 Stream 的头部以避免内存不足。最近在阅读大文件时被这个抓住了。 scala> Stream.continually(1).take(100000000).foreach(x=>()) 是可以的,但是 scala> val s = Stream.continually(1).take(100000000) s: scala.collection.immutable. Stream[Int] = Stream(1, ?) scala> s.foreach(x=>()) java.lang.OutOfMemoryError: Java heap space [ bah, cmets 中没有格式,参见 paste: paste.pocoo.org/show/226682 ] 除非你真的需要Stream,不如用Iterator.continually代替Stream.continually,这样你就不用担心Stream的问题了。 Right Seth,请参阅我对这个问题的回答:***.com/questions/3062804/scala-unit-type/…,有关 Stream 与 Iterator 的比较,请参阅***.com/questions/1527962/…。 @mkneissl 不知道为什么会发生 OOM 错误,您能否详细说明 OOM 问题? @MehdiB。 , 见scala-lang.org/api/current/scala/collection/immutable/… : """必须小心memoization;如果你不小心,你很快就会吃掉大量的内存。原因是Stream的memoization创建了一个很像scala的结构.collection.immutable.List。只要有东西抓住头部,头部就会抓住尾部,因此它会递归地继续。"""【参考方案4】:您正在编写 Scala 代码,就像用 Java 编写的那样。尝试以更类似于 Scala 的方式进行操作。要逐行读取文本文件并对每一行执行某些操作,请尝试以下操作:
import java.io.File
import scala.io.Source
Source.fromFile(new File("myfile.txt")).getLines.foreach line =>
// Do something with the line, for example print it
println(line)
【讨论】:
他没有做普通文件 IO。他在做 CSV IO。 @Ken CSV文件通常是面向行的文本文件,他上面的代码sn-p是关于逐行读取文本文件的。我的回答确实不是对他问题的直接回答,我只是想展示一种更适合 Scala 习语的方式;他的原始代码是 Scala 中的 Java 习语。【参考方案5】:Scala 中的赋值不返回值,Unit 类似于 C 或 C++ 中的 void。
试试
var line = ""
while (line = reader.readNext(); line != null) ...
这是因为返回了块中最后一个表达式的值,在这种情况下它是一个布尔值,这是 while
【讨论】:
Unit
在 Scala 中更类似于 void
而不是 null
。以上是关于Scala 单元类型的主要内容,如果未能解决你的问题,请参考以下文章