如何在Scala中轻松定义更复杂的PartialFunction?
PartialFunctions
在Scala中,一个 通过一系列的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是从定义部分功能的情况列表中自动生成的. 上下文 Lift框架在许多地方使用部分功能,例如以确定是否应该由Lift的引擎处理请求或直接从磁盘上的文件提供请求.有时候,我发现自己想写一个匹配所有输入参数的case语句,后来才决定是否要返回一个值.这意味着初始系列的情况还不足以确定我的函数是否定义在给定的值 例如,在Lift中,我想添加一个规则,直接提供所有html和htm文件,并且应该处理带有“lift”扩展名的文件.看起来很容易做这样的事情: LiftRules.liftRequest.prepend { case Req(path,extension,tpe) => extension match { case "html" | "htm" => false case "lift" => true } } 不幸的是,在这种情况下,编译器认为我的部分功能是无处不在的,因为第一种情况总是匹配的.这是嵌套的匹配,可能不符合所有传入的请求.而且,一个请求不匹配,一个MatchError被抛出. 题 是否有一种简单的方法使编译器在定义部分函数时考虑嵌套的匹配语句,或者是唯一的方式来内嵌所有嵌套的条件呢? LiftRules.liftRequest.prepend { case Req(path,tpe) if extension == "html" || extension == "htm" => false case Req(path,tpe) if extension == "lift" => true } 在这个例子中,它很大程度上是可行的,但是可读性降低了,而且我遇到了那些内联所有检查看起来非常丑陋的情况. 解决方法
在这种情况下,你可能想写
LiftRules.liftRequest.prepend { case Req(path,"html" | "htm",tpe) => false case Req(path,"lift",tpe) => true } 对于更复杂的情况,您需要定义自己的提取器,而不需要使用嵌套的case语句. object CheckExtension { def unapply(ext: String) = ext match { case "lift" => Some(true) case "html" | "htm" => Some(false) case _ => None } } LiftRules.liftRequest.prepend { case Req(path,CheckExtension(valid),tpe) => valid } 这将只匹配,如果您的预定义的未应用函数返回Some并将Some值赋给自由变量有效.如果取消应用返回None,则不会生成匹配项. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |