gpt4 book ai didi

scala - 如何在 Scala 中轻松定义更复杂的 PartialFunctions?

转载 作者:行者123 更新时间:2023-12-03 21:26:24 24 4
gpt4 key购买 nike

偏函数

在 Scala 中,一个 PartialFunction 简而言之,是一个额外定义了一个 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
isDefinedAtcase 的列表中自动生成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
}

在这个例子中,它在很大程度上是可行的,但可读性降低了,而且我遇到过内联所有检查看起来非常难看的情况。

最佳答案

在这种情况下,您可能需要编写

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
}

这仅在您预定义的 unapply 时匹配函数返回 Some并赋值 Some到自由变量 valid .如 unapply返回 None ,未生成匹配项。

关于scala - 如何在 Scala 中轻松定义更复杂的 PartialFunctions?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6609377/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com