在 Scala 的模式匹配系统中使用比较运算符
Posted
技术标签:
【中文标题】在 Scala 的模式匹配系统中使用比较运算符【英文标题】:Using comparison operators in Scala's pattern matching system 【发布时间】:2010-12-07 19:25:22 【问题描述】:是否可以使用 Scala 中的模式匹配系统进行比较匹配? 例如:
a match
case 10 => println("ten")
case _ > 10 => println("greater than ten")
case _ => println("less than ten")
第二个 case 语句是非法的,但我希望能够指定“当 a 大于时”。
【问题讨论】:
这也可以用来检查一个函数的计算结果是否为真,例如case x if x.size > 2 => ...
要理解的重要一点是 => 运算符左侧的“模式”确实是“模式”。您拥有的第一个 case 表达式中的 10 不是整数文字。所以,你不能在左边执行操作(比如>检查或者说函数应用isOdd(_))。
【参考方案1】:
虽然以上和以下所有答案都完美地回答了原始问题,但可以在文档 https://docs.scala-lang.org/tour/pattern-matching.html 中找到一些附加信息,它们不适合我的情况,但因为这个 *** 答案是谷歌中的第一个建议,我会喜欢发布我的答案,这是上述问题的一个极端案例。 我的问题是:
如何在带有参数的匹配表达式中使用保护 功能?可以转述:
如何在匹配表达式中使用带有 a 参数的 if 语句 功能?答案是下面的代码示例:
def drop[A](l: List[A], n: Int): List[A] = l match
case Nil => sys.error("drop on empty list")
case xs if n <= 0 => xs
case _ :: xs => drop(xs, n-1)
指向 scala fiddle 的链接:https://scalafiddle.io/sf/G37THif/2
如您所见,case xs if n <= 0 => xs
语句能够将 n(函数的参数) 与 guard(if) 语句一起使用。
我希望这对像我这样的人有所帮助。
【讨论】:
【参考方案2】:作为对问题精神的非回答,即询问如何将谓词合并到匹配子句中,在这种情况下,谓词可以在match
之前被分解:
def assess(n: Int)
println(
n compare 10 match
case 0 => "ten"
case 1 => "greater than ten"
case -1 => "less than ten"
)
现在,the documentation for scala.math.Ordering.compare(T, T)
只承诺不相等的结果将大于或小于零。 Java 的 Comparable#compareTo(T)
与 Scala 的指定类似。就像 Scala 的 current implementation 所做的那样,分别对正值和负值使用 1 和 -1 是一种惯例,但是如果没有从底层改变实现的风险,就不能做出这样的假设。
【讨论】:
我不确定您是否建议这是一个真正的解决方案,但我强烈建议您反对任何依赖于未记录的约定或假设的事情。 没错。这就是为什么我写了“一个人不能在没有风险的情况下做出这样的假设”,并将我的回答定性为“不回答”。考虑为什么compare()
和 compareTo()
不指定 0、1 和 -1 作为它们的共同域是很有趣的。
Math.signum(n compare 10) 将保证 -1、0 或 1。
今天早上,我确认在写下我的原始答案将近 六年 之后,即使有问题的实现从一种类型转移到另一种类型,Scala 仍然保持着返回的注意行为-1、0 或 1。
一个有效的答案,但我个人不喜欢这个。很容易忘记 0,1 和 -1 的含义。【参考方案3】:
我认为比添加警卫更具可读性的解决方案:
(n compare 10).signum match
case -1 => "less than ten"
case 0 => "ten"
case 1 => "greater than ten"
注意事项:
Ordered.compare
如果小于则返回负整数,如果大于则返回正整数,并且
0
如果相等。
Int.signum
将输出从 compare
压缩到 -1
用于负数(小于 10),1
用于正数(大于 10),或 0
用于零(等于 10)。
【讨论】:
【参考方案4】:您可以在模式后添加一个守卫,即if
和一个布尔表达式:
a match
case 10 => println("ten")
case x if x > 10 => println("greater than ten")
case _ => println("less than ten")
编辑:请注意,这与在=>
之后放置if
有很大不同,因为如果守卫是,则模式不会匹配不正确。
【讨论】:
本,很好的答案,它确实说明了模式保护的重要性。以上是关于在 Scala 的模式匹配系统中使用比较运算符的主要内容,如果未能解决你的问题,请参考以下文章