我是Scala的新手,我正在尝试对其结构进行解码,我了解了pattern matching,其语法类似于Java switch语句
val x: Int = Random.nextInt(10)
x match {
case 0 => "zero"
case 1 => "one"
case 2 => "two"
case _ => "other"
}
此代码非常明显且可读。我碰到了partial functions,很明显,很清楚它们是什么
部分函数是不为以下问题提供答案的函数 可以给出所有可能的输入值。
我很困惑的是在部分函数的主体中使用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: ?
不匹配的情况是否在部分函数之外的其他任何地方使用?
答案 0 :(得分:5)
这意味着仅当输入参数可以匹配大小写表达式时,才会应用部分函数。
生成的实际类如下:
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表达式的块表达式,而这些case表达式是编译器无法真正使用的。
答案 1 :(得分:2)
我将尝试回答这个问题:
我不了解没有match语句时如何使用大小写,怎么办 它由Scala解释,如何读取,是方法,类 或其他构造?
主要是参考this文章,我将对此进行引用和解释。
此方法起作用的原因:
val f: (Any) => String = {
case i: Int => "Int"
case d: Double => "Double"
case _ => "Other"
}
是编译器将其解释为匿名函数。
在创建 val 函数时,您真正用这样的代码所做的全部工作就是为匿名函数分配变量名。
为支持第一条陈述,《 Scala编程》第15.7节指出:
大括号中的一系列情况可以在可以使用函数文字的任何地方使用。
因此,与在filter
或collect
内部使用相同的语法并没有什么不同。
以上代码本质上创建了一个Function1
对象。正如this source所解释的:
PartialFunction和scala.Function1之间的主要区别是 PartialFunction的用户可以选择做某事 与声明在其域外的输入有所不同。
答案 2 :(得分:1)
这是the specification中所述的模式匹配匿名函数。
尝试此操作会出错
val SomeFun = ...
这是因为需要知道参数类型,就像“常规”匿名函数x => ...
一样。区别在于,在模式匹配匿名函数中,没有地方可以直接指定参数类型(等效于(x: Int) => ...
),因此,必须必须是预期的类型,例如val SomeFun: PartialFunction[Int, Int]
或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
}
}
答案 3 :(得分:0)
编译器翻译
val divide: PartialFunction[Int, Int] = {
case d: Int if d != 0 => 42 / d
}
类似于
def divide(d: Int) = {
if (d != 0)
42 / d
else
throw new MatchError(d)
}
回答
...我可以在没有
case
语句的情况下使用match
的其他方式
问自己一个问题,我们可以在哪里使用翻译后的def
版本。请注意,PartialFunction
定义如何具有不安全 throw
,这是要记住的重要方面。
作为一个旁注,使用case
子句定义函数与数学中的piecewise function定义相似。