【问题标题】:Scala Partial Function Type DefinitionScala偏函数类型定义
【发布时间】:2018-05-03 03:13:46
【问题描述】:
val even: PartialFunction[Int, String] = PartialFunction[Int, String] {
  case i if i % 2 == 0 => i + " is even"
}

val isEven: PartialFunction[Int, String] = {
  case i if i % 2 == 0 => i + " is even"
}

val odd: PartialFunction[Int, String] = PartialFunction[Int, String] {
  case x if x % 2 == 1 => x + " is odd"
}


val isOdd: PartialFunction[Int, String] = {
  case x if x % 2 == 1 => x + " is odd"
}

val tot = even orElse odd
val tot2 = isEven orElse isOdd

println(tot(3))
println(tot2(3))

在此代码中,tot 函数抛出匹配错误,而 tot2 函数按预期工作。它们之间的唯一区别是它们的定义方式。任何人都可以解释为什么结果如此不同吗?

提前致谢!!!

【问题讨论】:

    标签: scala partialfunction


    【解决方案1】:

    核心区别在于,部分函数上的 isDefinedAt 没有像您在使用 PartialFunction.apply 方法的版本上所期望的那样定义。这就是为什么现在不推荐使用此方法的原因,PartialFunction.apply 旨在将总函数转换为部分函数,​​isDefinedAt 始终返回 true,这意味着它会认为它在您的示例中定义为 3,并尝试应用该函数而不是回退到您提供的偶数函数作为替代方法。

    这在社区中提出了一个关于全功能与部分功能的共同痛点。 PartialFunction 是 Function 的子类型,我猜在 OO 设计意义上它是一个带有附加方法(isDefinedAt)的函数,它告诉您该函数是否是为特定值定义的。许多人认为这是一个错误,因为在 Liskov 的意义上,Function 应该是 PartialFunction 的子类型,因为您可以在任何期望 PartialFunction 的地方使用 Function,但是如果您在期望 Function 的地方使用 PartialFunction 它将编译,那么可能会失败在运行时。我的感觉是因为可以认为 Function 有一个隐含的 isDefinedAt 始终返回 true,这将允许您更正关系并使 Function 成为 PartialFunction 的子类型。这在 PartialFunction.apply 中达到了顶点,它期望一个总函数,并且由于这种期望将 isDefinedAt 定义为始终返回 true,但它不能强制执行该期望,所以如果你调用 PartialFunction.apply(somePartialFunction) 坏事大多数发生程序员不会想到的。

    PartialFunction.apply Scaladoc

    PartialFunction[Int, String]{...} is syntactic sugar for
    PartialFunction[Int, String].apply({...})
    

    最小化:

    val even: PartialFunction[Int, String] = PartialFunction[Int, String]{
      case i if i % 2 == 0 => i + " is even"
    }
    
    val isEven: PartialFunction[Int, String] = {
      case i if i % 2 == 0 => i + " is even"
    }
    
    println(even.isDefinedAt(3)) //true
    println(isEven.isDefinedAt(3)) //false
    

    【讨论】:

      【解决方案2】:

      在前两种情况下,您在PartialFunction 的伴随对象中调用apply 函数。我知道,这听起来好像应该 工作。但这不是因为PartialFunction.apply 应该读作PartialFunction.fromTotalFunction。

      这是一个 Scala 语言问题,如果我没记错的话(目前找不到票,稍后再看),这个 apply 函数将消失并在 Scala 2.13 中被 fromTotalFunction 取代。

      更新

      我的意思是票是#6005

      似乎PartialFunction.apply 自Scala 2.12.5 以来已被弃用。

      【讨论】:

        猜你喜欢
        • 2016-06-24
        • 1970-01-01
        • 2016-08-03
        • 1970-01-01
        • 1970-01-01
        • 2011-11-05
        • 1970-01-01
        • 2017-02-13
        • 2021-06-22
        相关资源
        最近更新 更多