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 单元类型的主要内容,如果未能解决你的问题,请参考以下文章

Scala基础——常用数据类型

scala的unit是啥意思?

Scala 基础—— 基础类型和基础操作

Scala 类型层次结构

必知|Scala类型层次结构

scala基本数据类型