模式匹配:使用 PartialFunction 拆分代码?
Pattern-matching: split code with PartialFunction?
我正在努力实现 "simple" 行为:将模式匹配代码分成两个单独的函数。
为了清晰起见,我正在简化模型:
abstract class Animal
case object Dog extends Animal
case object Cat extends Animal
case object Bird extends Animal
case object Bat extends Animal
case object Dolphin extends Animal
我想在不同的函数上对这些进行模式匹配(因为实际代码很长),但是还有其他参数所以 PartialFunctions 让我恶心...
在一个完美的世界里,我可以写:
type PF = PartialFunction[(Animal, Int, String), String]
private def processFlying(a: Animal, n: Int, loc: String): PF = {
a match {
case Bird => n + " birds found in " + loc
case Bat => n + " bats found in " + underground(loc)
}
}
private def processMarine(a: Animal, n: Int, loc: String): PF = {
a match {
case Dolphin => n + " dolphins found in " + submarine(loc)
}
}
private def processPet(a: Animal, n: Int, loc: String): PF = {
a match {
case Dog => n + " dogs found in " + loc
case Cat => n + " cats found in " + loc
}
}
def processAnimal(a: Animal, number: Int, location: String) = {
val processAll = processFlying orElse processMarine orElse processPet
processAll(a, n, location)
}
然而那是行不通的。主要是因为我的函数中需要几个参数。 "Why U no use tuples?"你说呢?好吧,我试过了,编译器不会停止抱怨预期类型与实际类型不同,并且与我的别名不同:(
任何帮助、提示或替代 IDE 都会有用!
干杯
编辑:
我遵循了 Cyrille 的回答,但我还需要在比赛前做一些工作,例如:
val processFlying: PF = {
// doSomething, like declare a sub-function f
{
case (b: Bird, n, loc) => f(b)
case (b: Bat, n, loc) => f(b)
}
}
你的问题是你混合了方法定义和函数定义。
def processFlying(a: Animal, n: Int, loc: String): PF
是一个方法(你周围对象的)的签名,它接受三个参数和return一个PF
,即一个PartialFunction[(Animal, Int, String), String]
.
所以,假设这个签名是你想要的,如果你已经有一个Animal
,一个Int
和一个[=18,你将只能得到一个PartialFunction
=]...
您更可能想要的是定义一个 PF
值(不带参数),所以更像是
val processFlying: PF = {
case (Bird, n, loc) => ...
case (Bat, n, loc) => ...
}
编辑
要回答你的第二个请求(虽然这可能有点矫枉过正,因为将你的助手定义为私有 def 就可以完成这项工作),你总是可以将 PF
块放在闭包中:
val processFlying = {
def f = ...
val res = {
case (Bird, n, loc) => f(...)
case (Bat, n, loc) => f(...)
}
res
}
但是,您必须为 PartialFunction
定义块分配一个值,否则解析器将不知道如何处理它。那只是因为 PartialFunction
定义 case
s 块和闭包共享 {}
语法。
我正在努力实现 "simple" 行为:将模式匹配代码分成两个单独的函数。
为了清晰起见,我正在简化模型:
abstract class Animal
case object Dog extends Animal
case object Cat extends Animal
case object Bird extends Animal
case object Bat extends Animal
case object Dolphin extends Animal
我想在不同的函数上对这些进行模式匹配(因为实际代码很长),但是还有其他参数所以 PartialFunctions 让我恶心...
在一个完美的世界里,我可以写:
type PF = PartialFunction[(Animal, Int, String), String]
private def processFlying(a: Animal, n: Int, loc: String): PF = {
a match {
case Bird => n + " birds found in " + loc
case Bat => n + " bats found in " + underground(loc)
}
}
private def processMarine(a: Animal, n: Int, loc: String): PF = {
a match {
case Dolphin => n + " dolphins found in " + submarine(loc)
}
}
private def processPet(a: Animal, n: Int, loc: String): PF = {
a match {
case Dog => n + " dogs found in " + loc
case Cat => n + " cats found in " + loc
}
}
def processAnimal(a: Animal, number: Int, location: String) = {
val processAll = processFlying orElse processMarine orElse processPet
processAll(a, n, location)
}
然而那是行不通的。主要是因为我的函数中需要几个参数。 "Why U no use tuples?"你说呢?好吧,我试过了,编译器不会停止抱怨预期类型与实际类型不同,并且与我的别名不同:(
任何帮助、提示或替代 IDE 都会有用!
干杯
编辑: 我遵循了 Cyrille 的回答,但我还需要在比赛前做一些工作,例如:
val processFlying: PF = {
// doSomething, like declare a sub-function f
{
case (b: Bird, n, loc) => f(b)
case (b: Bat, n, loc) => f(b)
}
}
你的问题是你混合了方法定义和函数定义。
def processFlying(a: Animal, n: Int, loc: String): PF
是一个方法(你周围对象的)的签名,它接受三个参数和return一个PF
,即一个PartialFunction[(Animal, Int, String), String]
.
所以,假设这个签名是你想要的,如果你已经有一个Animal
,一个Int
和一个[=18,你将只能得到一个PartialFunction
=]...
您更可能想要的是定义一个 PF
值(不带参数),所以更像是
val processFlying: PF = {
case (Bird, n, loc) => ...
case (Bat, n, loc) => ...
}
编辑
要回答你的第二个请求(虽然这可能有点矫枉过正,因为将你的助手定义为私有 def 就可以完成这项工作),你总是可以将 PF
块放在闭包中:
val processFlying = {
def f = ...
val res = {
case (Bird, n, loc) => f(...)
case (Bat, n, loc) => f(...)
}
res
}
但是,您必须为 PartialFunction
定义块分配一个值,否则解析器将不知道如何处理它。那只是因为 PartialFunction
定义 case
s 块和闭包共享 {}
语法。