orElse如何在PartialFunctions上工作 [英] How does orElse work on PartialFunctions
问题描述
使用 PartialFunction
上定义的或Else
方法,我得到了非常奇怪的行为(至少在我看来)
在我看来:
val a = PartialFunction [字符串,单位] {
casehello=> println(Bye)
}
val b:PartialFunction [Any,Unit] = a.orElse(PartialFunction.empty [Any,Unit])
a(hello)//再见
a(bogus)// MatchError
b(bogus)// Nothing
b(true)// Nothing
是有道理的,但这不是它的行为方式,我很难理解为什么,因为类型签名似乎表明我在上面暴露的内容。
以下是我在Scala 2.11.2中观察的结果:
欢迎使用Scala 2.11.2版(Java HotSpot™64位服务器VM,Java 1.8.0_11)。
键入表达式让他们评估。
输入:help获取更多信息。
scala> val a = PartialFunction [String,Unit] {
|情况你好=> println(Bye)
| }
a:PartialFunction [String,Unit] =< function1>
scala> a(hello)
再见
scala> a(bye)
scala.MatchError:bye(类java.lang.String)
at $ anonfun $ 1.apply(< console>:7)
at $ anonfun $ 1 .apply(< console> 7)
at scala.PartialFunction $$ anonfun $ apply $ 1.applyOrElse(PartialFunction.scala:242)
at scala.runtime.AbstractPartialFunction.apply(AbstractPartialFunction.scala: 36)
... 33消除
scala> val b = a.orElse(PartialFunction.empty [Any,Unit])
b:PartialFunction [String,Unit] =< function1>
scala> b(sdf)
scala.MatchError:sdf(类java.lang.String)
at $ anonfun $ 1.apply(< console>:7)
at $ anonfun $ 1 .apply(< console> 7)
at scala.PartialFunction $$ anonfun $ apply $ 1.applyOrElse(PartialFunction.scala:242)
at scala.PartialFunction $ OrElse.apply(PartialFunction.scala: 162)
... 33消除
请注意 val b
它没有扩大PartialFunction的类型。
但是这也不能按预期工作:
scala> val c = a.orElse(PartialFunction.empty [String,Unit])
c:PartialFunction [String,Unit] =< function1>
scala> c(sdfsdf)
scala.MatchError:sdfsdf(类java.lang.String)
at $ anonfun $ 1.apply(< console>:7)
at $ anonfun $ 1 .apply(< console> 7)
at scala.PartialFunction $$ anonfun $ apply $ 1.applyOrElse(PartialFunction.scala:242)
at scala.PartialFunction $ OrElse.apply(PartialFunction.scala: 162)
... 33消除了
您的尝试有一些问题,但首先让我们看看一个有效的实现:
scala> val a:PartialFunction [String,Unit] = {casehello=> println(bye)}
a:PartialFunction [String,Unit] =< function1>
scala> val b:PartialFunction [Any,Unit] = {case _ => println(fallback)}
b:PartialFunction [Any,Unit] =< function1>
scala> val c = a.orElse(b)
c:PartialFunction [String,Unit] =< function1>
scala> c(hello)
bye
scala> c(foo)
后备
代码中有两个主要错误: p>
- 定义PF的方式
- (错误)假设
空
是一个catch-all函数,返回Nothing
- (错误)假设
1。如何定义PartialFunction
val right:PartialFunction [String,Unit] = {
casehello=> ; println(bye)
}
定义它:
val错误= PartialFunction [字符串,单位] {
casehello=> println(bye)
}
如果您查看 PartialFunction.apply
def apply [A,B](f:A => ; B):PartialFunction [A,B] = {case x => f(x)}
你会发现它为 / em> x
,它将给定的 f
函数应用于它。现在你的 {casehello=> println(bye)}
是 f
参数,所以你最终会得到下面的结果(显然是意想不到的) PartialFunction
:
val错误:PartialFunction [String,Unit] = {
case x => x match {
casehello=> println(bye)
}
所以当你问它是否定义它会永远返回true,因为它是为任何字符串定义的:
wrong.isDefinedAt(hello)/ / true(ok)
wrong.isDefinedAt(whatever)// true(sure?)
但是当你尝试申请
它
错误( hello)// bye(ok)
错误(whatever)// MatchError(BOOM!)
由于 orElse
$ b
根据 isDefined
的结果决定是否调用else,这很明显为什么它失败。
2。空无一物!
def empty [A,B]:PartialFunction [A,B ]
具有空域的部分函数。任何尝试调用空的部分函数都会导致抛出
scala.MatchError
异常。
$ b $ val fallback:PartialFunction [Any,Unit] = {case _ => println(fallback)}
或者 - 为了表明我们从错误中学习 - p>
val fallback = PartialFunction [Any,Unit] {_ => println(fallback)}
I am getting very bizarre behavior (at least it seems to me) with the orElse
method defined on PartialFunction
It would seem to me that:
val a = PartialFunction[String, Unit] {
case "hello" => println("Bye")
}
val b: PartialFunction[Any, Unit] = a.orElse(PartialFunction.empty[Any, Unit])
a("hello") // "Bye"
a("bogus") // MatchError
b("bogus") // Nothing
b(true) // Nothing
makes sense but this is not how it is behaving and I am having a lot of trouble understanding why as the types signatures seem to indicate what I exposed above.
Here is a transcript of what I am observing with Scala 2.11.2:
Welcome to Scala version 2.11.2 (Java HotSpot(TM) 64-Bit Server VM, Java 1.8.0_11).
Type in expressions to have them evaluated.
Type :help for more information.
scala> val a = PartialFunction[String, Unit] {
| case "hello" => println("Bye")
| }
a: PartialFunction[String,Unit] = <function1>
scala> a("hello")
Bye
scala> a("bye")
scala.MatchError: bye (of class java.lang.String)
at $anonfun$1.apply(<console>:7)
at $anonfun$1.apply(<console>:7)
at scala.PartialFunction$$anonfun$apply$1.applyOrElse(PartialFunction.scala:242)
at scala.runtime.AbstractPartialFunction.apply(AbstractPartialFunction.scala:36)
... 33 elided
scala> val b = a.orElse(PartialFunction.empty[Any, Unit])
b: PartialFunction[String,Unit] = <function1>
scala> b("sdf")
scala.MatchError: sdf (of class java.lang.String)
at $anonfun$1.apply(<console>:7)
at $anonfun$1.apply(<console>:7)
at scala.PartialFunction$$anonfun$apply$1.applyOrElse(PartialFunction.scala:242)
at scala.PartialFunction$OrElse.apply(PartialFunction.scala:162)
... 33 elided
Note the return type of val b
which has not widen the type of the PartialFunction.
But this also does not work as expected:
scala> val c = a.orElse(PartialFunction.empty[String, Unit])
c: PartialFunction[String,Unit] = <function1>
scala> c("sdfsdf")
scala.MatchError: sdfsdf (of class java.lang.String)
at $anonfun$1.apply(<console>:7)
at $anonfun$1.apply(<console>:7)
at scala.PartialFunction$$anonfun$apply$1.applyOrElse(PartialFunction.scala:242)
at scala.PartialFunction$OrElse.apply(PartialFunction.scala:162)
... 33 elided
There's a few things wrong with your attempt, but first let's see a working implementation:
scala> val a: PartialFunction[String, Unit] = { case "hello" => println("bye") }
a: PartialFunction[String,Unit] = <function1>
scala> val b: PartialFunction[Any, Unit] = { case _ => println("fallback") }
b: PartialFunction[Any,Unit] = <function1>
scala> val c = a.orElse(b)
c: PartialFunction[String,Unit] = <function1>
scala> c("hello")
bye
scala> c("foo")
fallback
There's two main errors in your code:
- the way the PF is defined
- the (wrong) assumption that
empty
is a "catch-all" function that returnsNothing
1. How to define a PartialFunction
val right: PartialFunction[String, Unit] = {
case "hello" => println("bye")
}
How not to define it:
val wrong = PartialFunction[String, Unit] {
case "hello" => println("bye")
}
If you look at the definition of PartialFunction.apply
def apply[A, B](f: A => B): PartialFunction[A, B] = { case x => f(x) }
you'll see that it defines a partial function for any x
and it applies the given f
function to it. Now your { case "hello" => println("bye") }
is the f
argument, so you approximately end up with the following (clearly unexpected) PartialFunction
:
val wrong: PartialFunction[String, Unit] = {
case x => x match {
case "hello" => println("bye")
}
So when you ask whether it's defined it will always return true, since it's defined for any string:
wrong.isDefinedAt("hello") // true (ok)
wrong.isDefinedAt("whatever") // true (sure?)
but when you try to apply
it
wrong("hello") // bye (ok)
wrong("whatever") // MatchError (BOOM!)
you fall short on the inner match.
Since orElse
decides whether to call the "else" depending on the result of isDefined
, then it's obvious why it fails.
2. Empty catches nothing!
Straight from the docs:
def empty[A, B]: PartialFunction[A, B]
The partial function with empty domain. Any attempt to invoke empty partial function leads to throwing
scala.MatchError
exception.
The PartialFunction
(well, it's not really partial anymore) you're looking for is:
val fallback: PartialFunction[Any, Unit] = { case _ => println("fallback") }
or - just to show that we learn from our mistakes -
val fallback = PartialFunction[Any, Unit] { _ => println("fallback") }
这篇关于orElse如何在PartialFunctions上工作的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!