我正在尝试调试为什么某些部分功能组合不起作用时我注意到,根据你如何实例化部分功能,你会得到不同的结果。
当你使用语法糖方法时,它都按预期工作:
scala> val pf1:PartialFunction[Any,Unit] = {case "a" => println("AAA")}
pf1: PartialFunction[Any,Unit] = <function1>
scala> val pf2:PartialFunction[Any,Unit] = {case "b" => println("BBB")}
pf2: PartialFunction[Any,Unit] = <function1>
scala> val pf = pf1 orElse pf2
pf: PartialFunction[Any,Unit] = <function1>
scala> pf("a")
AAA
scala> pf("b")
BBB
但是,如果使用PartialFunction对象,它将不再起作用。
scala> val pf1 = PartialFunction[Any,Unit]{case "a" => println("AAA")}
pf1: PartialFunction[Any,Unit] = <function1>
scala> val pf2 = PartialFunction[Any,Unit]{case "b" => println("BBB")}
pf2: PartialFunction[Any,Unit] = <function1>
scala> val pf = pf1 orElse pf2
pf: PartialFunction[Any,Unit] = <function1>
scala> pf("a")
AAA
scala> pf("b")
scala.MatchError: b (of class java.lang.String)
at $anonfun$1.apply(<console>:7)
为什么?您通常会期望Object的apply方法的行为类似于Class的构造函数。
答案 0 :(得分:3)
文档说Object的apply方法将普通函数转换为部分函数,但它没有详细说明。显然,isDefinedAt
始终返回true
:
scala> val pf1 = PartialFunction[Any,Unit]{case "a" => println("AAA")}
pf1: PartialFunction[Any,Unit] = <function1>
scala> pf1.isDefinedAt("a")
res14: Boolean = true
scala> pf1.isDefinedAt("b")
res15: Boolean = true
这将导致pf1
始终捕获输入。所以我猜结论是小心如何实例化部分函数。
答案 1 :(得分:0)
PartialFunction Object中的apply方法将普通函数转换为部分函数。阅读文档here因此,声明的部分函数被视为普通函数并输入为PartialFunction。无论在那里实现什么,该函数的域都成为普通函数的所有域。因此,pf1最终消耗所有输入并且从不调用orElse函数。
答案 2 :(得分:0)
正如其他人所指出的,PartialFunction.apply
将普通函数转换为部分函数。
这是唯一合理的方法,因为普通函数的域是未知的(就PartialFunction.apply
而言),是创建一个定义在任何地方的部分函数。
因此,当您编写PartialFunction[Any,Unit] { case "a" => println("AAA") }
时,您实际上正在创建两个部分函数:传递到apply
方法的函数和apply
返回的函数} 方法。它们几乎相同,只是返回的函数在任何地方定义,而不仅仅是"a"
。