前两天看到有篇关于Option的小文章,上面引用NullPointer的发明人C.A.R. Hoare老先生说的一句话:空引用是一个“十亿美元的错误”(http://en.wikipedia.org/wiki/Null_pointer#Null_pointer)。
当时以为这里主要说的是返回值为空时会导致出现空指针异常,而返回值如果用Option包一下,就总会返回一个对象,再也不会返回空引用了,也不会有NullPointerException了。这种认识没有错,不过直到今晚看play框架的初始化代码,才清楚认识到Option到底有什么用处,到底如何能节省“10亿美元”。
play框架初始化时会根据配置创建一个NettyServer,过程如下:
def main(args: Array[String]) {
args.headOption.orElse(
Option(System.getProperty("user.dir"))).map(new File(_)).filter(p => p.exists && p.isDirectory).map { applicationPath =>
createServer(applicationPath).getOrElse(System.exit(-1))
}.getOrElse {
println("Not a valid Play application")
}
}
初看有点晕,这么长的一串,又是map,又是filter,还不断有orElse,getOrElse,搞不懂到底是什么意思。只好回过头来先研究下Option的代码:
@inline final def getOrElse[B >: A](default: => B): B =
if (isEmpty) default else this.get
可以看出,getOrElse的意思是,如果Option为空,就返回参数的值,否则返回Option的值。顺便插一句,这里的参数值类型前有个“=>”,是延后求值的,就是所谓的call-by-name参数:如果Option不为空,参数根本就不会求值。看到这里,想起了我们产品代码中一堆如下java代码:
if (log.isDebugEnabled())
{
log.debug("plaplapla");
}
如果用scala,把log.debug的参数定义为call-by-name的参数,就只有一行搞定。C++中的做法是定义一个宏,也是很难看的解决方案。
再看map:
@inline final def map[B](f: A => B): Option[B] =
if (isEmpty) None else Some(f(this.get))
如果Option为空,返回空Option,否则返回经过函数f映射后的Option。这里的None和Some是Option的子类,分别代表没有和有。
filter类似:
@inline final def filter(p: A => Boolean): Option[A] =
if (isEmpty || p(this.get)) this else None
如果为空,或者p函数返回false,返回空Option,否则返回自己。
再回过头看最初的5行代码,立刻感觉到Option的巨大优势了:做了这么多参数准备和验证,又是判断空,又是判断文件是否存在以及是否为目录,居然没有任何if语句!没有if else的一个副作用是错误处理也非常优雅。这段代码如果用java写的话,大概是这样子的:
public static void main(String[] args) {
String dir = null;
if (args.length == 1)
dir = args[0];
else
dir = System.getProperty("user.dir");
if (dir != null)
{
File f = new File(dir);
if (f.exists() && f.isDirectory())
{
NettyServer server = createServer(f);
if (server == null)
System.exit(-1);
}
else
System.out.println("not a valid play application");
}
else
System.out.println("xxxx");
}
代码行长短先不说,以前感觉这种java代码逻辑很清晰,现在却觉得这些if else这么别扭,错误处理这么难受。
再回过头来看scala的其他代码,发现基本上没有if语句。这种感觉有点像前两天刚刚开始用erlang的时候,发现erlang代码中几乎没有if语句一样,最初极其别扭,发现不会写程序了,不过很快,就是用case语句爽得很了。
看了scala,不想写java了。
分享到:
相关推荐
Scala语言分析报告
Scala语言规范-Scala 是一门类 Java 的编程语言,它结合了面向对象编程和函数式编程。 Scala 是纯面向对象的,每个值都是一个对象,对象的类型和行为由类定义,不同的类可以通过混入(mixin)的方式组合在一起。 Scala...
第 1 章 SCALA 的概述 11.1 学习 SDALA 的原因11.2 SCALA 语言诞生小故事 1以及 JVM 的关系分析图21.4 SCALA 语言的
《Scala语言规范》非常有利于spark的学习。希望能够帮助到大家。
Scala语言入门
Scala语言规范.zip
Scala是一门类Java的编程语言,它结合了面向对象编程和函数式编程。Scala是纯面向对象的,每个值都是一个对象,对象的类型和行为由类定义,不同的类可以通过混入(mixin)的方式组合在一起。
尚硅谷大数据scala语言核心编程,是大数据开发必备的技能。
scala 从入门到精通以及各种使用规范,使用技巧的文档
快学Scala、scala函数式编程、Scala编程实战:三本书籍,带目录和标签
JAVA+Scala语言开发基于机器学习的商品类目预测源码+文档说明.zip本资源中的源码都是经过本地编译过可运行的,评审分达到95分以上。资源项目的难度比较适中,内容都是经过助教老师审定过的能够满足学习、使用需求,...
完整的ID3决策树算法,采用了scala语言来实现,代码完整。
最好的scala 学习课件,最好的scala 学习课件,学习spark必备
本项目是基于Scala语言开发的Apache Spark学习与实践源码,共包含53个文件。其中,Scala源代码文件21个,文本文件7个,XML文件5个,Markdown文档5个,JSON配置文件3个,Avro Schema文件2个,CSV数据文件2个,...
自己在学习大数据的相关内容的时候,学习了Scala,记录了大部分知识点,可供参考
学习Scala语言,不仅仅意味着熟悉新的API,更重要的是一种思维方式的转变。从原有的面向对象编程(OO)到函数式编程(FP)的思想。本书面向实际的使用场景,提供了大量的Scala实例,同时,也给出底层的原理和相关的...
大数据利器之scala开发语言文档,非常详细,一步步讲解。 spark开发语言scala,同样的结果java100行,scala10行。需要樱桃笔记打开
Scala 是一门类 Java 的编程语言,它结合了面向对象编程和函数式编程。Scala 是 纯面向对象的,每个值都是一个对象,对象的类型和行为由类定义,不同的类可以通过混 入(mixin)的方式组合在一起。Scala 的设计目的是...
Scala-学习资料-mht.rar。Scala学习资料 mht网页格式。