第三章 函数式编程中的异常处理
一. 函数式编程中的异常处理
(本章将自己实现scala标准库中的Option,Either)
-
异常的优点和劣势
(1)函数抛出异常导致成为偏函数// 偏函数版mean,没有对所有输入做定义,比如对空的seq会抛出异常 // 如果函数对所有输入都能返回Double,就是完全函数 // 因此,为了改造成纯函数,可以把抛出异常,改为Double类型的某个特殊值,比如Double.NaN。但是这样,函数的调用者就必须知道如何处理这个特殊的返回值。由于特殊情况的存在,也就破坏了引用透明 // 所以,接下来设计一种推迟返回值获取,来替代异常抛出的Option类 def mean(xs:Seq[Double]):Double = { if (xs.isEmpty) throw new ArithmeticException("mean of empty list!") else xs.sum/xs.length }
(2)构造Option类族,包装结果
scala sealed trait Option[+A] case class Some[+A](get:A) extends Option[A] case object None extends Option[Nothing]
(3)改造mean函数为纯函数
scala /**利用Option类包装结果*/ def mean2(xs:Seq[Double]):Option[Double] = { if(xs.isEmpty) None else Some(xs.sum/xs.length) }
2. Either对异常处理
(1)Option不能表现出异常情况下发生了什么,只会返回一个None。Either作为对Optiond的扩展,可以跟踪失败原因
(2)Right和Left是Either的两个子类,Right表示结果正确,Left表示结果错误
```scala
def mean(xs:IndexedSeq[Double]):Either[Exception,Double] = {
try Right(1/0)
catch {
case e:Exception => Left(e)
}
}
```