scala语言学习之Option

前两天看到有篇关于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了。

 

你可能感兴趣的:(option)