偏函数
简而言之,在 Scala 中,aPartialFunction
是一个额外定义isDefinedAt
方法的函数。
用一系列case
语句很容易定义偏函数。一个简单的例子是,例如:
scala> val pf: PartialFunction[Int, Unit] = {
| case 42 => ()
| }
pf: PartialFunction[Int,Unit] = <function1>
scala> pf.isDefinedAt(42)
res0: Boolean = true
scala> pf.isDefinedAt(0)
res1: Boolean = false
isDefinedAt
case
是从定义偏函数的 s 列表中自动生成的。
语境
Lift 框架在很多地方都使用了部分函数,例如,定义一个请求是应该由 Lift 的引擎处理还是直接从磁盘上的文件提供服务。有时,我发现自己想编写一个case
匹配所有输入参数的语句,然后才决定是否要返回一个值。这意味着case
s 的初始序列不再足以确定我的函数是否定义为给定值
例如,在 Lift 中,我想添加一条规则,直接提供所有 html 和 htm 文件,并且应该处理带有“lift”扩展名的文件。做这样的事情看起来很容易:
LiftRules.liftRequest.prepend {
case Req(path, extension, tpe) => extension match {
case "html" | "htm" => false
case "lift" => true
}
}
不幸的是,在这种情况下,编译器认为我的部分函数在任何地方都定义了,因为第一个case
总是匹配的。它是嵌套的match
,可能不匹配所有传入的请求。并且,是一个请求不匹配,一个MatchError
被抛出。
问题
有没有一种简单的方法可以让编译器match
在定义部分函数时考虑嵌套语句,或者是唯一的方法来内联所有这样的嵌套条件?
LiftRules.liftRequest.prepend {
case Req(path, extension, tpe) if extension == "html" || extension == "htm" => false
case Req(path, extension, tpe) if extension == "lift" => true
}
在这个例子中,它在很大程度上是可行的,但是可读性降低了,而且我遇到过内联所有检查看起来非常难看的情况。