【问题标题】:Partial Functions in ScalaScala 中的部分函数
【发布时间】:2016-09-08 17:46:17
【问题描述】:

我只是想澄清一些有关 Scala 中部分定义的函数的内容。我查看了文档,它说偏函数的类型是PartialFunction[A,B],我可以定义一个偏函数,例如

val f: PartialFunction[Any, Int] = {...}

我想知道,对于AB 类型,A 是一个参数,而B 是一个返回类型吗?如果我有多个接受的类型,我是否使用orElse 将部分函数链接在一起?

【问题讨论】:

  • 是的,这是正确的想法。

标签: scala


【解决方案1】:

在函数的集合论视图中,如果函数可以将域中的每个值映射到范围内的值,我们就说这个函数是total function。在某些情况下,函数无法将域中的某些元素映射到范围;此类函数称为partial functions

以 Scala 文档中的部分函数为例:

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

这里定义了一个偏函数,因为它被定义为仅将偶数整数映射到字符串。所以偏函数的输入是整数,输出是字符串。

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

isOdd 是另一个与isEven 类似定义的偏函数,但用于奇数。同样,偏函数的输入是整数,输出是字符串。

如果您有一个数字列表,例如:

List(1,2,3,4,5)

并在此列表上应用isEven 部分函数,​​您将得到输出

List(2 is even, 4 is even)

请注意,并非原始列表中的所有元素都已被偏函数映射。但是,在某些情况下,您可能希望在部分函数无法将元素从域映射到范围的情况下应用另一个函数。在这种情况下,我们使用orElse

val numbers = sample map (isEven orElse isOdd)

现在你会得到输出:

List(1 is odd, 2 is even, 3 is odd, 4 is even, 5 is odd)

【讨论】:

  • 应用 isEven 函数究竟是什么意思。如果它意味着 map "List(1, 2, 3, 4, 5) map isEven" 它将导致 scala.MatchError: 1 (of class java.lang.Integer)
  • @AbhishekGayakwad,没有。在这种情况下,您必须使用 collect。您不能使用map,因为odd 数字显然会失败。 collect 首先使用isDefinedAt 函数进行检查。
【解决方案2】:

如果您希望设置一个实际上接受多个参数的偏函数,请在您将要输入的参数元组上定义偏函数,例如:

val multiArgPartial: PartialFunction[(String, Long, Foo), Int] = {
  case ("OK", _, Foo("bar", _)) => 0 // Use underscore to accept any value for a given parameter
}

当然,确保将参数作为元组传递给它。

【讨论】:

    【解决方案3】:

    除了其他答案之外,如果“多种接受的类型”是指您希望接受相同的功能,例如StringIntBoolean(没有其他类型),这被称为“联合类型”,目前在 Scala 中不受支持(但计划在未来基于 Dotty)。替代方案是:

    1. 使用最不常见的超类型(Any 用于上述情况)。这就是orElsechains 会做的事情。
    2. 使用像Either[String, Either[Int, Boolean]] 这样的类型。如果您有两种类型,这很好,但很快就会变得丑陋。
    3. 将联合类型编码为negation of intersection types

    【讨论】:

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