Scala单位类型

Don*_* Ch 31 scala while-loop

我使用opencsv来解析csv文件,我的代码是

while( (line = reader.readNext()) != null ) { .... }
Run Code Online (Sandbox Code Playgroud)

我收到编译器警告说:

 comparing values of types Unit and Null using `!=' will always yield true
 [warn]     while( (aLine = reader.readNext()) != null ) {
Run Code Online (Sandbox Code Playgroud)

我应该怎么做while循环?

mkn*_*ssl 71

赋值表达式Unit在Scala中具有类型.这就是编译器警告的原因.

Scala中有一个很好的习惯用法可以避免while循环:

val iterator = Iterator.continually(reader.readNext()).takeWhile(_ != null)
Run Code Online (Sandbox Code Playgroud)

这为您提供了任何reader.readNext返回的迭代器.

continually方法返回一个"无限"迭代器并takeWhile获取其前缀,但不包括第一个null.

(斯卡拉2.8)

  • 是否值得指出,这个"迭代器"不会急切地评估,不像"while"块会急切地_execute_? (2认同)

Vas*_*iuk 20

在你的情况下(line = reader.readNext())是一个返回类型Unit的功能文字.您可以按如下方式重写代码:

while( {line = reader.readNext();  line!= null} ) { .... }
Run Code Online (Sandbox Code Playgroud)

  • 我坚持评论,我很害怕.这不是惯用语.它甚至没有比*functional*答案更多的性能,因为你的代码将编译成一个函数(即对象)实例化 (10认同)
  • 请不要接受这个答案:虽然这不是惯用的Scala,但有更好的方法可以实现你想要的东西(见下面的答案) (8认同)
  • @oxbow_lakes,也许你在这里有点严厉?在核心团队的2.8标准库中,while关键字被使用了数百次,这个答案是高效的,简洁的,最重要的是,看起来也像我的答案; @)) (3认同)

oxb*_*kes 17

你可以用a Stream来得到你想要的东西:

Stream.continually(reader.readLine()).takeWhile( _ ne null) foreach { line =>
  //do Stuff
}
Run Code Online (Sandbox Code Playgroud)

这还有其他很酷的东西的额外优势:

Stream.continually(reader.readLine()).takeWhile( _ ne null) match {
  case head #:: tail => //perhaps you need to do stuff with the first element?
  case _             => //empty
}
Run Code Online (Sandbox Code Playgroud)

编辑 - 感谢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
Run Code Online (Sandbox Code Playgroud)

  • 您可能希望添加警告,以避免流的头部以避免内存不足.最近在读取大文件时已经被这个抓住了.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堆空间[bah,评论中没有格式化,请参阅pastie:http://paste.pocoo .org/show/226682 /] (3认同)
  • 除非你真的需要一个Stream,你不妨使用Iterator.continually而不是Stream.continually,然后你不用担心Stream的问题. (2认同)

Jes*_*per 10

您正在编写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)
}
Run Code Online (Sandbox Code Playgroud)