Bas*_*ato 12 functional-programming scala exception-handling
所以我正在学习Scala的功能,并且书中说异常会破坏引用透明度,因此Option应该使用它,如下所示:
def pattern(s: String): Option[Pattern] = {
try {
Some(Pattern.compile(s))
} catch {
case e: PatternSyntaxException => None
}
}
Run Code Online (Sandbox Code Playgroud)
这看起来很糟糕; 我的意思是它似乎相当于:
catch(Exception e){
return null;
}
Run Code Online (Sandbox Code Playgroud)
除了我们可以区分"null for error"和"null as genuine value"这一事实.它似乎应该至少返回包含错误信息的内容,如:
catch {
case e: Exception => Fail(e)
}
Run Code Online (Sandbox Code Playgroud)
我错过了什么?
Mau*_*res 11
在这个特定的部分,Option主要用作一个例子,因为使用的操作(计算mean)是一个部分函数,它不会为所有可能的值生成一个值(集合可能是空的,因此没有办法计算均值)这Option可能是一个有效的案例.如果你无法计算mean因为集合是空的,只需返回一个None.
但是还有很多其他方法可以解决这个问题,你可以使用Either[L,R],因为Left它是错误的结果,并且Right因为它是一个很好的结果,你仍然可以抛出异常并将其包装在一个Try对象中(现在这似乎更常见,因为它是使用Promise和Future计算),你可以使用ScalaZ验证如果错误实际上是一个验证问题.
您应该从这一部分开始的主要概念是错误应该是函数的返回类型的一部分,而不是类型无法合理声明的一些魔术操作(异常).
作为一个无耻的插件,我做了关于Either和尝试的博客.
如果你没有问"为什么比例外Option更好?",那么回答这个问题会更容易.并且"为什么Option比null更好?" 并且"为什么Option比这更好Try?" 一切都在同一时间.
第一个问题的答案是,在非真正特殊的情况下使用异常会混淆程序的控制流程.这就是引用透明度的地方 - 如果我能够根据值思考并且不必跟踪异常被抛出和捕获的位置,那么我(或您)更容易推理您的代码.
第二个问题的答案(为什么不为null?)就像"你曾经NullPointerException在Java中处理过吗?".
对于第三个问题,一般来说你是对的 - 最好使用类似的类型Either[Throwable, A]或Try[A]表示可能失败的计算,因为它们允许您传递有关失败的更详细信息.但是,在某些情况下,当一个函数只能以一种明显的方式失败时,使用它是有意义的Option.例如,如果我在地图中执行查找,我可能并不真正需要或想要类似的东西Either[NoSuchElementException, A],其中错误是如此抽象,以至于我可能最终将它包装在更具特定领域的东西中.所以get在地图上只返回一个Option[A].