【问题标题】:Empty partial function in ScalaScala中的空部分函数
【发布时间】:2011-08-25 10:38:13
【问题描述】:

在我看来,部分函数的{ case ... => ... } 语法至少需要一个case

scala> val pf: PartialFunction[String, String] = { case "a" => "b" } 
pf: PartialFunction[String,String] = <function1>

scala> val pf: PartialFunction[String, String] = { }                
<console>:5: error: type mismatch;
 found   : Unit
 required: PartialFunction[String,String]
       val pf: PartialFunction[String, String] = { }
                                                 ^

那么,定义“空”部分函数的最佳方法是什么?有没有比“手动”覆盖isDefinedAtapply 更好的方法?

【问题讨论】:

标签: scala partialfunction


【解决方案1】:

Map 是一个 PartialFunction,所以你可以这样做:

val undefined: PartialFunction[Any, Nothing] = Map.empty

【讨论】:

  • 实际上还有被大量记录不足的FSM.NullFunction(它做同样的事情)。我现在正在添加文档。
  • 自 2.10 PartialFunction.empty 可用
【解决方案2】:

从 Scala 2.10 开始,您可以使用:

val emptyPf = PartialFunction.empty[String, String]

【讨论】:

    【解决方案3】:
    scala> def pfEmpty[A, B] = new PartialFunction[A, B] {
         |   def apply(a: A): B = sys.error("Not supported")
         |   def isDefinedAt(a: A) = false
         | }
    pfEmpty: [A, B]=> java.lang.Object with PartialFunction[A,B]
    
    scala> val f = pfEmpty[String, String]
    f: java.lang.Object with PartialFunction[String,String] = <function1>
    
    scala> f.lift
    res26: (String) => Option[String] = <function1>
    
    scala> res26("Hola")
    res27: Option[String] = None
    

    正如@didird 在 cmets 中所说,由于参数差异,单个实例可以涵盖所有可能的参数类型。

    scala> object Undefined extends PartialFunction[Any, Nothing] {
         |   def isDefinedAt(a: Any) = false
         |   def apply(a: Any): Nothing = sys.error("undefined")
         | }
    defined module Undefined
    
    scala> val f: PartialFunction[String, String] = Undefined
    f: PartialFunction[String,String] = <function1>
    
    scala> f.lift apply "Hola"
    res29: Option[String] = None
    

    【讨论】:

    • @Nicolas:是的,定义一个为你做这件事的函数。 (pfEmpty 这里) ;)
    • @Nicolas:说实话,当我读到这个问题时,我错过了那句话。感谢您指出!我知道我的问题不满足问题中指定的约束,但无论如何我把它留在这里,希望它可能对某人有用。
    • 考虑到参数差异,单个实例可以完成所有工作:object Undefined[Any, Nothing] {... your impl ...}
    • 我的帖子中有两个问号。 @missingfaktor 对第一个给出了很好的答案,并在第二个中含蓄地说 “我不知道”。 :-) +1!
    • 不应该应用引发 s​​cala.MatchError 异常?这就是应用未为输入定义的 PF 通常所做的事情。
    【解决方案4】:

    从每个人那里偷东西,可能是这一切的混合:

    val undefined : PartialFunction[Any, Nothing] = {case _ if false =>
      sys.error("undefined")
    }
    

    【讨论】:

    • sys.error 有什么用?它永远不会被执行。
    • @aioobe:它有一个类型Nothing
    • Nothing 类型更加独立的表达式,可以替换 sys.error 调用:undefined(undefined)。
    【解决方案5】:

    我能想到的最短的一个:

    { case _ if false => "" }
    

    【讨论】:

    • 您不需要在=&gt; 之后添加"" 以使其成为有效的PartialFunction[String, String]。如果是这样,这有点不幸,因为它绑定到"" 的结果类型,不是吗? (似乎另一种选择是做=&gt; throw new RuntimeException(),但这可能更丑陋。)你的经历是什么?
    • @aioobe 你会的。我没注意PF的类型。
    • 是否将"" 更改为null(或其他任何内容?)使其适用于所有可能的部分函数(不仅仅是返回String 的部分函数)?
    • @aioobe 否。要使其普遍适用,您必须使用error 或类似的东西,因为它们返回NothingNothing 是所有事物的唯一子类型。
    【解决方案6】:

    一种解决方案(更像是一种 hack)是确保这种情况永远不会成立:{ case x if x != x =&gt; sys.error("unexpected match") }

    单纯的好奇,为什么需要这样的功能?

    【讨论】:

    • 我有一个接受部分函数的 API,我想为它提供一个未为任何参数定义的部分函数。
    【解决方案7】:

    知道计划向 scala 库添加一个空成员并查看它是如何实现的可能会很有趣: https://github.com/scala/scala/commit/6043a4a7ed5de0be2ca48e2e65504f56965259dc

    【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-08-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-10-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多