orElse如何在PartialFunctions上工作 [英] How does orElse work on PartialFunctions

查看:124
本文介绍了orElse如何在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>


  1. 定义PF的方式
  2. (错误)假设是一个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:

  1. the way the PF is defined
  2. the (wrong) assumption that empty is a "catch-all" function that returns Nothing

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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆