Geo*_*Geo 7 scala scala-option
作为文章的结果,我读到了Option有助于避免NullPointerException的类,我开始在整个地方使用它.想象一下这样的事情:
var file:Option[File] = None
Run Code Online (Sandbox Code Playgroud)
以后当我使用它时:
val actualFile = file.getOrElse(new File("nonexisting"))
if(actualFile.getName.equals("nonexisting")) { // instead of null checking
}
else { // value of file was good
}
Run Code Online (Sandbox Code Playgroud)
做这样的事情对我来说感觉不那么"正确".我也注意到.get已经被弃用了..这种东西是你们用Option做的,或者我走错了路?
Rex*_*err 15
返回Option然后getOrElse用来产生一些意味着"未找到"的哨兵值通常不是一个好主意.这就是为什么Option设计:表示没有找到值!
Option真正体现出它的力量与像函数编程结构结合使用时map和foreach.在处理多个选项时,这是最有效的.例如,假设我编写了一个接受字符串并返回文件的方法,但只有当文件存在并且文件不是目录时:
import java.io._;
def niceFile1(s: String): File = {
val f = new File(s);
if (f.exists && !f.isDirectory) f else null
}
def niceFile2(s: String): Option[File] = {
val f = new File(s);
if (f.exists && !f.isDirectory) Some(f) else None
}
Run Code Online (Sandbox Code Playgroud)
到目前为止,使用起来null更容易 - 至少在您忘记这可能会给您null并且您获得NPE之前.无论如何,我们现在尝试使用它.
def niceFopen1(s: String) = {
val f = niceFile1(s);
if (f!=null) new FileInputStream(f) else null;
}
def niceFopen2(s: String) = niceFile2(s).map(f => new FileInputStream(f))
Run Code Online (Sandbox Code Playgroud)
看看发生了什么!在前一种情况下,我们必须手动进行逻辑测试并创建临时变量.啊! 在第二种情况下,map为我们完成了所有脏工作:None映射到None,并Some(file)映射到Some(fileinputstream).简单!
但它变得更好了.也许我们想找到一大堆文件的大小:
def totalSize2(ss: Seq[String]) = {
(0L /: ss.flatMap(niceFile2)){(sum,f) => sum+f.length}
}
Run Code Online (Sandbox Code Playgroud)
等等,这里发生了什么 - 所有这一切None呢?我们不是必须注意并以某种方式处理它们吗?嗯,这就是它的所在flatMap:它将所有答案连接在一起. None是零长度的答案,所以它忽略了它. Some(f)有一个答案 - f- 它把它放在列表中.然后我们使用折叠来累加所有长度 - 现在列表中的所有元素都是有效的.挺棒的!
oxb*_*kes 12
不解决它的值Option,但将逻辑应用于它包含的任何内容是一个好主意:
findFile.foreach(process(_))
Run Code Online (Sandbox Code Playgroud)
基本上这会处理一个File如果找到一个并且什么都不做(并且相当于托马斯的第一个for理解因为for编译到一个调用foreach).它是一个更简洁的版本:
findFile match {
case Some(f) => process(f)
case None =>
}
Run Code Online (Sandbox Code Playgroud)
更重要的是,关于这一点的好处是你可以连锁经营,例如:
(findLiveFile orElse fileBackupFile orElse findTempFile).foreach(process(_)
Run Code Online (Sandbox Code Playgroud)
在大多数情况下,您将使用模式匹配
file match {
case Some(f) => { .. } //file is there
case _ => { .. } //file is not there
}
Run Code Online (Sandbox Code Playgroud)
如果您只对该文件感兴趣,则可以使用for表达式
for(f <- file) { //file is there
}
Run Code Online (Sandbox Code Playgroud)
然后,您可以链接表达式以在容器上的多个级别上工作
for{
option <- List(Some(1), None, Some(2))
f <- option
} yield f
res0: List[Int] = List(1, 2)
Run Code Online (Sandbox Code Playgroud)
或者你可以使用isDefined并得到:
if(option.isDefined) {
val x = option.get;
} else {
}
Run Code Online (Sandbox Code Playgroud)
Scala 2.8.0.Beta-1中不推荐使用get.