考虑代码:
def MatchSmth(someInt: Int, offset: Int = 1): Int = {
someInt match {
case `offset` + 3 => 123123
case `offset` + 4 => 22
case `offset` + 5 => 123
case invalid => -1
}
}
编译错误:scala not found: value +
Equivalent1:
def MatchSmth(someInt: Int, offset: Int = 1): Int = {
if (someInt == offset + 3) 123123
else if (someInt == offset + 4) 22
else if (someInt == offset + 5) 123
else -1
}
Equivalent2:
def MatchSmth(someInt: Int, offset: Int = 1): Int = {
someInt match {
case v if v == `offset` + 3 => 123123
case v if v == `offset` + 4 => 22
case v if v == `offset` + 5 => 123
case invalid => -1
}
}
除了equivalent1和equivalent2之外,是否有类似于此代码的内容?为什么Scala不允许在匹配器中使用这种构造(带算术)?
答案 0 :(得分:2)
从技术上讲,Scala不允许在其规范中使用它。这已在answer from Suma中描述。
从概念上讲,模式匹配的概念不是if-then-else或解决方程的好捷径,而是使用解构来提供定义部分函数,类似于Lisp。对于此任务,Scala使用所谓的"提取器"。
提取器与构造函数相反。从技术上讲,Scala使用方法" unapply"分解其部分中的给定对象。 Unapply接受对象并返回布尔值,可选原子值或可选元组。或者,也有unapplySeq,它可以返回一系列值。然后,Scala尝试将结果与给定的参数列表进行匹配。当匹配可能时,Scala使用给定的参数名称解除原子值或元组的一部分。 (有关详细信息,请参阅this paper)
示例:
case class Pet(name: String, age : Int)
Pet("Polly", 86) match {
case Pet(name, _) => println(s"Hello ${name}")
}
// This will print: Hello Polly
Scala将创建一个对象Pet("Polly", 86)
。然后它会将该对象赋予match
之后定义的部分函数。此函数将调用该对象上的Pet.unapply(...)
并检查结果是否为Some(Tuple[Int,_])
形状。如果为true,它将变量name
绑定到该元组的第一个成员,并使用println
函数调用给定的操作。
Scala仅检查unapply
结果的形状。从理论上讲,它可以更加努力地尝试将不适用的结果与给定变量统一起来。这有助于简单的情况,例如您的示例中的情况。但在更复杂的情况下,它会带来巨大的运行时惩罚。从理论上讲,统一甚至可以无限循环。
如果匹配不是幻想,但使用解构。它并没有在统一方面付出任何努力,而是按照“原样”和#34;进行操作。这对于保持生成的代码很快是必要的。
答案 1 :(得分:1)
你可以写
def MatchSmth(someInt: Int, offset: Int = 1): Int = {
(someInt - offset) match {
case 3 => 123123
case 4 => 22
case 5 => 123
case _ => -1
}
}
答案 2 :(得分:1)
没有。模式的Scala grammar是:
8.1模式
Syntax: Pattern ::= Pattern1 { ‘|’ Pattern1 } Pattern1 ::= varid ‘:’ TypePat | ‘_’ ‘:’ TypePat | Pattern2 Pattern2 ::= varid [‘@’ Pattern3] | Pattern3 Pattern3 ::= SimplePattern | SimplePattern {id [nl] SimplePattern} SimplePattern ::= ‘_’ | varid | Literal | StableId | StableId ‘(’ [Patterns] ‘)’ | StableId ‘(’ [Patterns ‘,’] [varid ‘@’] ‘_’ ‘*’ ‘)’ | ‘(’ [Patterns] ‘)’ | XmlPattern Patterns ::= Pattern {‘,’ Patterns}
如您所见,literal
(8.1.4文字模式)或StableId
(8.1.5稳定标识符模式)是允许的,而不是常量表达式。您现在可以问 - 是否有一些重要原因导致不允许持续表达?如果允许持续表达,语法是否仍能明确地工作?我不知道。