3

我是 Scala 的新手,我正在尝试解码它的结构,我了解了模式匹配,语法类似于 Java switch 语句

val x: Int = Random.nextInt(10)

x match {
  case 0 => "zero"
  case 1 => "one"
  case 2 => "two"
  case _ => "other"
}

这里的代码非常明显且可读。我遇到了部分功能,它们非常明显并且很清楚它们是什么

偏函数是一个函数,它不能为它可以给出的每个可能的输入值提供答案。

我感到困惑的是case在这样的部分函数的主体中使用:

val divide2: PartialFunction[Int, Int] = {
    case d: Int if d != 0 => 42 / d // WHAT IS THIS ?! 
}

我不明白如何case在没有match语句的情况下使用,Scala 如何解释它,它是如何读取的,它是一个方法、一个类还是另一个构造?,我可以case在没有match语句的情况下使用哪些其他方式

编辑:

我试图玩弄这个案例,但仍然没有得到它。例如

val SomeFun: PartialFunction[Int, Int] = {
    case d: Int if d != 0 => 1000 / d
    case f: Int if f != 2 => 100 / f
    case m: Int if m != 1 => 10 / m
  }

这是如何运作的?

尝试这样做会出错

val SomeFun = {
    case d: Int if d != 0 => 1000 / d
    case f: Int if f != 2 => 100 / f
    case m: Int if m != 1 => 10 / m
  }


Error:(29, 17) missing parameter type for expanded function
The argument types of an anonymous function must be fully known. (SLS 8.5)
Expected type was: ?

不匹配的大小写是否在偏函数之外的其他任何地方使用?

4

3 回答 3

6

这意味着只有当输入参数可以匹配 case 表达式时才会应用部分函数。

生成的实际类是这样的:

val divide = new PartialFunction[Int, Int] {
    def apply(x: Int) = 42 / x
    def isDefinedAt(x: Int) = x != 0
}

使用 orElse 您可以应用或处理多个定义:

funcForInt orElse funcForDouble orElse funcForString

构图不错?

编辑:

val SomeFun: PartialFunction[Int, Int] = {
    case d: Int if d != 0 => 1000 / d
    case f: Int if f != 2 => 100 / f
    case m: Int if m != 1 => 10 / m
  }

以上是使用匿名类功能。如果你删除变量的类型,你只是给它一个块表达式,其中包含一些编译器不能真正使用的 case 表达式。

参考:https ://www.james-willett.com/scala-anonymous-classes

于 2019-10-16T05:05:55.217 回答
4

我将尝试回答这个问题:

我不明白如何在没有 match 语句的情况下使用 case,Scala 如何解释它,它是如何读取的,它是一个方法、一个类还是另一个构造?

主要是参考我将引用和解释的这篇文章。

这样做的原因:

val f: (Any) => String = {
    case i: Int => "Int"
    case d: Double => "Double"
    case _ => "Other"
}

是编译器将其解释为匿名函数。

当您创建val函数时,您真正使用这样的代码所做的就是将变量名分配给匿名函数。

为了支持第一个陈述,Scala 编程的第 15.7 节指出:

花括号中的一系列 case 可以在任何可以使用函数字面量的地方使用。

filter因此,它与在or内部使用相同的语法并没有真正的不同collect

上面的代码本质上是创建一个Function1对象。正如此消息来源所解释的:

PartialFunction 和 scala.Function1 之间的主要区别是 PartialFunction 的用户可以选择对声明在其域之外的输入执行不同的操作。

于 2019-10-16T05:58:40.500 回答
4

它是规范中描述的模式匹配匿名函数。

尝试这样做会出错

val SomeFun = ...

这是因为需要知道参数类型,就像“普通”匿名函数一样x => ...。不同之处在于,在模式匹配匿名函数中,没有地方直接指定参数类型(相当于(x: Int) => ...),因此必须有预期的类型,例如val SomeFun: PartialFunction[Int, Int]or val SomeFun: Int => Int

val SomeFun: PartialFunction[Int, Int] = {
    case d: Int if d != 0 => 1000 / d
    case f: Int if f != 2 => 100 / f
    case m: Int if m != 1 => 10 / m
  }

被翻译成

val SomeFun: PartialFunction[Int, Int] = new PartialFunction[Int, Int] {
  override def apply(x: Int) = x match {
    case d: Int if d != 0 => 1000 / d
    case f: Int if f != 2 => 100 / f
    case m: Int if m != 1 => 10 / m
  }
  override def isDefined(x: Int) = x match {
    case d: Int if d != 0 => true
    case f: Int if f != 2 => true
    case m: Int if m != 1 => true
    case _ => false
  }
}
于 2019-10-16T17:53:10.260 回答