加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > 安全 > 正文

scala 2.8控制异常 – 有什么意义?

发布时间:2020-12-16 09:43:25 所属栏目:安全 来源:网络整理
导读:在即将到来的scala 2.8中,添加了一个util.control包,其中包含一个中断库和一个用于处理异常的构造,以使代码看起来像: type NFE = NumberFormatExceptionval arg = "1"val maybeInt = try { Some(arg.toInt) } catch { case e: NFE = None } 可以用以下代
在即将到来的scala 2.8中,添加了一个util.control包,其中包含一个中断库和一个用于处理异常的构造,以使代码看起来像:

type NFE = NumberFormatException
val arg = "1"
val maybeInt = try { Some(arg.toInt) } catch { case e: NFE => None }

可以用以下代码替换:

import util.control.Exception._
val maybeInt = catching(classOf[NFE]) opt arg.toInt

我的问题是为什么?除了提供另一种(和完全不同)的方式来表达同样的东西,这增加了什么语言?有没有什么可以使用新的控件表达,但不能通过try-catch?它是一个DSL应该使Scala中的异常处理看起来像其他语言(如果是,哪一个)?

解决方法

有两种方法来考虑异常。一种方法是将它们视为流量控制:异常会更改程序的执行流程,从而使执行从一个位置跳转到另一个位置。第二种方法是将它们视为数据:异常是有关程序执行的信息,然后可以将其用作程序其他部分的输入。

C和Java中使用的try / catch范例是第一种(*)。

但是,如果您希望将异常作为数据处理,则必须使用所显示的代码。对于简单的情况,这很简单。然而,当涉及组合是国王的功能性风格时,事情开始变得复杂。你要么复制代码,要么滚动自己的库来处理它。

因此,在一种旨在支持功能和OO风格的语言中,不要惊讶地看到图书馆支持将异常视为数据。

并注意到,异常处理事情有许多其他的可能性。例如,您可以使用链接捕获处理程序,其方式与Lift链部分功能相一致,以便轻松地将责任委托给处理网页请求。

以下是可以做的事情的一个例子,因为自动资源管理现在很流行:

def arm[T <: java.io.Closeable,R](resource: T)(body: T => R)(handlers: Catch[R]):R = (
  handlers 
  andFinally (ignoring(classOf[Any]) { resource.close() }) 
  apply body(resource)
)

这使您可以安全关闭资源(请注意使用忽略),并且仍然适用您可能想要使用的任何捕捉逻辑。

(*)奇怪的是,Forth的异常控制,catch& throw是混合的。流程从throw跳到catch,但是这些信息被视为数据。

编辑

好的,我屈服了我举个例子。一个例子,就是这样!我希望这不是太设计,但是没有办法。这种事情在大型框架中最为有用,而不是小样本。

无论如何,我们首先定义与资源有关的一些事情。我决定打印行和返回打印的行数,这里是代码:

def linePrinter(lnr: java.io.LineNumberReader) = arm(lnr) { lnr =>
  var lineNumber = 0
  var lineText = lnr.readLine()
  while (null != lineText) {
    lineNumber += 1
    println("%4d: %s" format (lineNumber,lineText))
    lineText = lnr.readLine()
  }
  lineNumber
} _

这是这个功能的类型:

linePrinter: (lnr: java.io.LineNumberReader)(util.control.Exception.Catch[Int]) => Int

所以,arm收到一个通用的Closeable,但是我需要一个LineNumberReader,所以当我调用这个函数时,我需要传递一下。然而,我返回的是一个函数Catch [Int] => Int,这意味着我需要将两个参数传递给linePrinter以使其工作。现在我们来看一下读者:

val functionText = """def linePrinter(lnr: java.io.LineNumberReader) = arm(lnr) { lnr =>
  var lineNumber = 1
  var lineText = lnr.readLine()
  while (null != lineText) {
    println("%4d: %s" format (lineNumber,lineText))
    lineNumber += 1
    lineText = lnr.readLine()
  }
  lineNumber
} _"""

val reader = new java.io.LineNumberReader(new java.io.StringReader(functionText))

那么现在呢,让我们用吧。一,一个简单的例子:

scala> linePrinter(new java.io.LineNumberReader(reader))(noCatch)
   1: def linePrinter(lnr: java.io.LineNumberReader) = arm(lnr) { lnr =>
   2:          var lineNumber = 1
   3:          var lineText = lnr.readLine()
   4:          while (null != lineText) {
   5:            println("%4d: %s" format (lineNumber,lineText))
   6:            lineNumber += 1
   7:            lineText = lnr.readLine()
   8:          }
   9:          lineNumber
  10:        } _
res6: Int = 10

如果我再试一次,我得到这个:

scala> linePrinter(new java.io.LineNumberReader(reader))(noCatch)
java.io.IOException: Stream closed

现在假设如果发生任何异常,我想返回0。我可以这样做:

linePrinter(new java.io.LineNumberReader(reader))(allCatch withApply (_ => 0))

这里有趣的是,我完全将异常处理(try / catch的catch部分)与资源的关闭完全分离,这是通过finally完成的。此外,错误处理是一个可以传递给该函数的值。至少,它使嘲笑try / catch / finally语句更容易。

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读