【问题标题】:Why does not Set implement PartialFunction?为什么 Set 不实现 PartialFunction?
【发布时间】:2013-09-03 19:54:19
【问题描述】:

在 Scala 中编程:全面的分步指南,第 2 版,第 546 页:

在 Iterable 下的继承层次结构中,您可以找到三个特征:Seq、 设置和映射。这三个特征的一个共同方面是它们都 用它的 apply 和 isDefinedAt 实现 PartialFunction trait 方法。

但是,此代码无法编译(尝试了 2.8.2 和 2.10.2):

Set(1, 2, 3).isDefinedAt(1)

有错误:

value isDefinedAt is not a member of scala.collection.immutable.Set[Int]

这是书中的错误吗?

【问题讨论】:

  • 我的猜测是isDefinedAt 是一个测试元素是否存在于集合中,而Setapplycontains 代替了这项工作。我的意思是,Sets 通常(并非总是)几乎仅用于测试元素是否存在。
  • 是的,这对我来说显然是拼写错误。
  • @cdshines - isDefinedAt 用于检查是否为给定的参数值定义了偏函数。见scala-lang.org/api/current/index.html#scala.PartialFunction
  • @Lee,在作为存在测试的集合的上下文中,这不是很清楚吗?
  • @cdshines - 这不是存在测试,它返回是否为某些输入值定义了函数,而不是它会返回 true。如果你有类似val f: PartialFunction[Int, Bool] = case { 1 => true } 的东西,那么f(2) 甚至都没有定义。在这种情况下,isDefinedAt(2) 返回 false,而f(2) 将抛出异常。

标签: scala


【解决方案1】:

确实看起来像。到 Scala 2.5.0:

  • SeqMap 扩展 PartialFunction:
  • Set 没有。

这似乎是明智的:Set 从对象映射到 Boolean 值,所以它总是定义true 用于成员,false 用于非成员)。

【讨论】:

  • 没错,它总是被定义的,这就是为什么Set 扩展Function1[A, Boolean] 而不是PartialFunction[A, ???]
  • 请注意,FunctionN也是部分的。在 Scala 中无法保证整体性。 FunctionNPartialFunction 之间的区别是 not 一个是部分的,另一个不是。不同之处在于,一个人知道偏心的概念并且可以对其进行审问,而另一个人则不知道。所以,这并不像你暗示的那样明显,Set 不能用isDefinedAt(_: T) = true 实现PartialFunction[T, Bool]
  • @JörgWMittag :我想我总体上理解你的陈述(虽然我不明白你为什么说“你不能保证 Scala 的整体性” - 需要详细说明吗?)。然而,这里的重点更多是扩展PartialFunction为开发人员 带来了一些语义权重:您看到标题并可能认为“哎呀,对于某些值,应用它可能会以某种不寻常的方式工作”。每个Function 扩展PartialFunction 都是完全正确的,但我认为这种方法没有任何好处,而且最大的缺点是噪音。
  • @TheTerribleSwiftTomato,Scala 中的所有函数都是部分函数,​​这意味着函数可能无法为某些输入返回值(例如,def x(i: Int) = 1 / x 是部分函数,​​因为 x(0) 不计算值;相反, def y(i: Int) = i + 1 是总的,因为它具有您可以传递给它的任何整数的值)。 PartialFunction 的子类形式化了函数的偏向性 - 它允许您通过 isDefinedAt 测试函数是否会针对给定的输入终止 - 而不是仅仅调用它并让它返回值或发散。
  • @Bill : true, 'y' 除了是总函数外,也是一个偏函数。这就是我在 API 中提到 noise 的原因 - 您可以将 PartialFunction 设为“可选”,用于所有功能(或者只是那些您不想以这种方式自省的功能),或者您坚持使用数学定义并使 every 函数成为PartialFunction。但话又说回来:isDefinedAt 也是一个函数。但是,如果有人觉得我的回答在这方面有误导性,我很乐意对其进行编辑。
【解决方案2】:

在数学中,偏函数 X => Y 是函数 X' → Y,其中 X' 是 X 的子集。将 Set 命名为 PartialFunction 是不正确的,因为它是一个全函数 - 它定义在每个元素。

这就是为什么Set(1, 2, 3).isDefinedAt _ 没有意义——它总是等于true

如前所述,Set[T] extends T => Boolean,无论元素是否存在,apply 方法的结果都是真或假。如果你愿意,你可以创建

trait NamedSet[T] extends Set[T] with PartialFunction[T,Boolean] {
   def isDefinedAt(x: T) = true
}

如你所见,这没有意义

【讨论】:

    猜你喜欢
    • 2021-05-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-09-14
    • 2011-01-11
    • 1970-01-01
    • 2021-01-03
    相关资源
    最近更新 更多