我认为这段代码不起作用,但它确实如此(在Scala 2.10中):
scala> ((i: Int) => i.toString match {
| case s if s.length == 2 => "A two digit number"
| case s if s.length == 3 => "A three digit number"
| }): PartialFunction[Int,String]
res0: PartialFunction[Int,String] = <function1>
// other interactions omitted
scala> res0.orElse(PartialFunction((i: Int) => i.toString))
res5: PartialFunction[Int,String] = <function1>
scala> res5(1)
res6: String = 1
它是如何工作的?我希望将MatchError
放在res0
内。
Scala语言规范似乎没有明确说明应该如何解释res0
。
答案 0 :(得分:3)
诀窍是编译器不会将您的定义解释为转换为部分函数的总函数 - 它实际上是首先创建部分函数。您可以通过注明res0.isDefinedAt(1) == false
。
如果您实际上将总函数转换为部分函数,您将获得预期的行为:
scala> PartialFunction((i: Int) => i.toString match {
| case s if s.length == 2 => "A two digit number"
| case s if s.length == 3 => "A three digit number"
| })
res0: PartialFunction[Int,String] = <function1>
scala> res0 orElse ({ case i => i.toString }: PartialFunction[Int, String])
res1: PartialFunction[Int,String] = <function1>
scala> res1(1)
scala.MatchError: 1 (of class java.lang.String)
// ...
在此示例中,PartialFunction.apply
将其参数视为总函数,因此有关其定义位置的任何信息都将丢失。
答案 1 :(得分:2)
orElse
上定义了 PartialFunction
,以便在未定义原始对象时将该参数视为回退。请参阅the API。
答案 2 :(得分:1)
你说如果res0
不匹配,你想尝试其他的pf。这基本上是如何工作的:
if (res0.isDefinedAt(1)) {
res0(1)
} else {
other(1)
}
orElse调用创建OrElse
的实例,该实例继承自PartialFunction
:https://github.com/scala/scala/blob/master/src/library/scala/PartialFunction.scala#L159
现在,当您apply
致电OrElse
时,会致电f1.applyOrElse(x, f2)
:https://github.com/scala/scala/blob/master/src/library/scala/PartialFunction.scala#L162
这将调用if (isDefinedAt(x)) apply(x) else f2(x)
:https://github.com/scala/scala/blob/master/src/library/scala/PartialFunction.scala#L117-L118
因此,只有当pf的匹配时,你才会获得MatchError
。