poi*_*ist 6 scala pattern-matching partial-functions
如何在以下声明中确定头部和尾部:
val head::tail = List(1,2,3,4);
//head: 1 tail: List(2,3,4)
Run Code Online (Sandbox Code Playgroud)
不应该有一些代码将第一个元素提取为head并将尾部作为新List返回.我一直在梳理Scala标准库代码,但我找不到/理解这是怎么做的.
这里涉及的 Scala 构造是Extractor。该符号::
只不过是 Scala 中的一个案例类,其中unapply
其伴生对象上存在一个方法来实现提取魔法。 这是关于提取器的很好的深入教程。但总结如下:
unapply
每当您想要“解包”类的内容时,无论是为了变量绑定还是作为模式匹配的一部分,编译器都会在表达式左侧的任何符号上查找方法。这可能是一个对象、一个案例类伴随对象(如::
您问题中的 )或带有unapply
. 的参数unapply
是要解包的传入类型,返回类型是Option
已声明为预期结构和类型的类型。在模式匹配中,aNone
表示未找到匹配项。在变量绑定中,如果结果是,MatchError
则抛出a 。None
一个好的思考方式unapply
是它是 的逆apply
。其中unapply
函数调用语法的接收者unapply
是提取器调用的接收者。
为了进一步说明这一点,让我们定义一个简单的案例类:
case class Cat(name: String, age: Int)
Run Code Online (Sandbox Code Playgroud)
因为它是一个案例类,所以我们会在伴生对象上自动生成apply
方法unapply
,大致如下所示:
object Cat {
// compiler generated...
def apply(name: String, age: Int) = new Cat(name, age)
def unapply(aCat: Cat): Option[(String, Int)] = Some((aCat.name, aCat.age))
}
Run Code Online (Sandbox Code Playgroud)
当您创建Cat
via 伴随对象时,apply
会被调用。当您解压 a 的组成部分时Cat
,unapply
称为:
val mycat = Cat("freddy", 3) // `apply` called here
...
val Cat(name, age) = mycat // `unapply` called here
...
val animal: AnyRef = mycat
val info = animal match {
case Cat(name, age) => "My pet " + name // `unapply` called here
case _ => "Not my pet"
}
// info: String = My pet freddy
Run Code Online (Sandbox Code Playgroud)
因为unapply
返回 an Option
,所以我们有很大的能力编写提取器来处理更有趣的情况,例如,在提取值之前测试传入类型是否符合某些条件。例如,假设我们想要获取“老”猫的名字。有人可能会这样做:
object OldCatName {
def unapply(aCat: Cat) = if (aCat.age >= 10) Some(aCat.name) else None
}
Run Code Online (Sandbox Code Playgroud)
用法与生成的相同unapply
:
val yourcat = Cat("betty", 12)
...
val OldCatName(name1) = yourcat
// name1: String = "betty"
val OldCatName(name2) = mycat
// scala.MatchError: Cat(freddy,3) (of class Cat)
Run Code Online (Sandbox Code Playgroud)
MatchError
允许 s 并不是一件好事,所以让我们使用模式匹配:
val conditions = Seq(mycat, yourcat) map {
case OldCatName(oldie) => s"$oldie is old"
case Cat(name, age) => s"At age $age $name is not old"
}
// conditions: Seq[String] = List(At age 3 freddy is not old, betty is old)
Run Code Online (Sandbox Code Playgroud)
unapply
该方法涉及的一个额外的魔力::
是允许val ::(head, tail) = ...
编写一些语法糖val head :: tail = ...
。
归档时间: |
|
查看次数: |
1102 次 |
最近记录: |