让我们从代码中执行此操作。首先,一个小的重写:
object & { def unapply[A](a: A) = Some(a, a) }
"Julie" match {
// case Brothers(_) & Sisters(_) => "Julie has both brother(s) and sister(s)"
case &(Brothers(_), Sisters(_)) => "Julie has both brother(s) and sister(s)"
case Siblings(_) => "Julie's siblings are all the same sex"
case _ => "Julie has no siblings"
}
新的重写意味着完全相同。注释行对提取器使用中缀表示法,第二行使用普通表示法。它们都翻译成同一个东西。
因此,Scala 会反复将“Julie”提供给提取器,直到所有未绑定的变量都分配给 Some 事物。第一个提取器是&,所以我们得到这个:
&.unapply("Julie") == Some(("Julie", "Julie"))
我们得到了Some,所以我们可以继续比赛。现在我们有一个包含两个元素的元组,并且我们在 & 中也有两个提取器,所以我们将元组的每个元素提供给每个提取器:
Brothers.unapply("Julie") == ?
Sisters.unapply("Julie") == ?
如果这两个都返回Some,那么匹配成功。只是为了好玩,让我们在没有模式匹配的情况下重写这段代码:
val pattern = "Julie"
val extractor1 = &.unapply(pattern)
if (extractor1.nonEmpty && extractor1.get.isInstanceOf[Tuple2]) {
val extractor11 = Brothers.unapply(extractor1.get._1)
val extractor12 = Sisters.unapply(extractor1.get._2)
if (extractor11.nonEmpty && extractor12.nonEmpty) {
"Julie has both brother(s) and sister(s)"
} else {
"Test Siblings and default case, but I'll skip it here to avoid repetition"
}
} else {
val extractor2 = Siblings.unapply(pattern)
if (extractor2.nonEmpty) {
"Julie's siblings are all the same sex"
} else {
"Julie has no siblings"
}
看起来丑陋的代码,即使没有优化只在extractor11 不为空的情况下得到extractor12,并且没有应该在有注释的地方出现代码重复。所以我会用另一种风格来写它:
val pattern = "Julie"
& unapply pattern filter (_.isInstanceOf[Tuple2]) flatMap { pattern1 =>
Brothers unapply pattern1._1 flatMap { _ =>
Sisters unapply pattern1._2 flatMap { _ =>
"Julie has both brother(s) and sister(s)"
}
}
} getOrElse {
Siblings unapply pattern map { _ =>
"Julie's siblings are all the same sex"
} getOrElse {
"Julie has no siblings"
}
}
开头flatMap/map的模式暗示了另一种写法:
val pattern = "Julie"
(
for {
pattern1 <- & unapply pattern
if pattern1.isInstanceOf[Tuple2]
_ <- Brothers unapply pattern1._1
_ <- Sisters unapply pattern1._2
} yield "Julie has both brother(s) and sister(s)
) getOrElse (
for {
_ <- Siblings unapply pattern
} yield "Julie's siblings are all the same sex"
) getOrElse (
"julie has no siblings"
)
您应该能够运行所有这些代码并亲自查看结果。