加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > 安全 > 正文

scala – orElse如何处理PartialFunctions

发布时间:2020-12-16 09:27:44 所属栏目:安全 来源:网络整理
导读:使用PartialFunction上定义的orElse方法,我得到了非常奇怪的行为(至少在我看来) 在我看来: val a = PartialFunction[String,Unit] { case "hello" = println("Bye")}val b: PartialFunction[Any,Unit] = a.orElse(PartialFunction.empty[Any,Unit])a("hello
使用PartialFunction上定义的orElse方法,我得到了非常奇怪的行为(至少在我看来)

在我看来:

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

有道理,但这不是它的表现方式,我很难理解为什么类型签名似乎表明我在上面暴露了什么.

以下是我使用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

请注意val b的返回类型,它没有扩展PartialFunction的类型.

但这也不能按预期工作:

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

解决方法

你的尝试有一些问题,但首先让我们看看一个有效的实现:

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

您的代码中存在两个主要错误:

>定义PF的方式
>(错误的)假设empty是一个返回Nothing的“catch-all”函数

1.如何定义PartialFunction

val right: PartialFunction[String,Unit] = {
  case "hello" => println("bye")
}

如何定义它:

val wrong = PartialFunction[String,Unit] {
  case "hello" => println("bye")
}

如果你看一下PartialFunction.apply的定义

def apply[A,B](f: A => B): PartialFunction[A,B] = { case x => f(x) }

你会看到它定义了任何x的部分函数,??它将给定的f函数应用于它.现在你的{case“hello”=> println(“bye”)}是f参数,所以你最终得到以下(明显意外的)PartialFunction:

val wrong: PartialFunction[String,Unit] = {
  case x => x match {
    case "hello" => println("bye")  
  }

因此,当您询问它是否已定义时,它将始终返回true,因为它是为任何字符串定义的:

wrong.isDefinedAt("hello") // true (ok)
wrong.isDefinedAt("whatever") // true (sure?)

但是当你尝试应用它时

wrong("hello") // bye (ok)
wrong("whatever") // MatchError (BOOM!)

你不能完成内心的比赛.

由于orElse决定是否根据isDefined的结果调用“else”,因此很明显它失败的原因.

空无所事!

直接从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.

您正在寻找的PartialFunction(好吧,它不再是部分的)是:

val fallback: PartialFunction[Any,Unit] = { case _ => println("fallback") }

或 – 只是为了表明我们从错误中吸取教训 –

val fallback = PartialFunction[Any,Unit] { _ => println("fallback") }

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读