为什么Scala要求模式变量是线性的?

为什么Scala要求模式变量是线性的?,scala,pattern-matching,Scala,Pattern Matching,Scala要求模式变量是线性的,即模式变量 变量在一个模式中不能出现多次。因此,本示例不编译: def tupleTest(tuple: (Int, Int)) = tuple match { case (a, a) => a case _ => -1 } 但您可以使用两个模式变量和一个保护来检查相等性: def tupleTest(tuple: (Int, Int)) = tuple match { case (a, b) if a == b => a ca

Scala要求模式变量是线性的,即模式变量 变量在一个模式中不能出现多次。因此,本示例不编译:

def tupleTest(tuple: (Int, Int)) = tuple match {
  case (a, a) => a
  case _ => -1
}
但您可以使用两个模式变量和一个保护来检查相等性:

def tupleTest(tuple: (Int, Int)) = tuple match {
  case (a, b) if a == b => a
  case _ => -1
}
那么为什么Scala要求模式变量是线性的呢?有没有个案不能这样转变呢

编辑 将第一个示例转换为第二个示例(Scala到Scala)很容易。在模式中变量
v
的所有匹配项中,取首先计算的表达式并将其分配给变量
v
。对于每一次出现,引入一个新变量,该变量的名称不在当前范围内使用。对于这些变量中的每一个
v'
添加一个保护
v==v'
。这和程序员的做法一样(=>同样的效率)。这种方法有什么问题吗?我希望看到一个不能像这样转换的例子。

因为
案例(a,b)
基本上是将
val a
赋值给
。\u1
val b
赋值给
。\u2
(至少你可以这样查看它)。如果是
情况(a,a)
,则不能将
值a
同时分配给
.\u 1
.\u 2

实际上,你想做的事情应该是

case (a, `a`) => ???

因为scala使用倒勾来匹配标识符。但不幸的是,这仍然不起作用,因为只有在
=>
之后才给出
a
的可见性(虽然这会很有趣,但如果a=b=>,我也讨厌写
案例(a,b))。这可能是因为很难编写一个支持“匹配文字”的编译器,在这种情况下,a不是文字。文字是“a”或0,a是外部作用域的标识符。(这种混淆可能来自于背景标记中的标识符被称为文字标识符)。@Suma你肯定是对的,谢谢。我已经修正了答案,请看我的编辑。如果a==b
,我将把
case(a,a)
作为
case(a,b)的语法糖引入。我在编辑的问题中描述了如何自动生成此代码。这种方法是否考虑不周全?@MegaMuetzenMike我认为
案例(a,a)
没有任何意义。您将case视为与scala中的任何其他表达式相同的表达式,但事实并非如此<代码>案例(a,)
对于将
a
分配给模式后面的对象具有非常特殊的意义。你不能只写
案例(a,a)
而期望第一个
a
和第二个
a
表现不同。在scala中,您只能通过1)
如果
2)倒勾符号3)使用以大写开头的变量来比较模式匹配中的某些内容,这就是规范定义的方式,您建议只更改所有内容there@MegaMuetzenMike你可以开始讨论改变现状的建议,scala开发团队中就有这样的邮件列表。这样的地方也不是这样的。另一种方法是为此编写scala宏,但鉴于scala中模式匹配的特殊意义,我不确定这是否容易实现,因为模式匹配器的指定和实现将非常困难。在第一个示例中,两次使用
a
有什么好处?提到
案例(a,b)
是否更清楚,其中
a
b
是不同的名称?另外,
linear
是编译器的一个术语吗
Unique
似乎是一个更好的词,但我没有任何编译器理论背景。这个例子选择得不好,但它很简单,并且显示了术语
linear
的含义,这个术语在我大学的一次讲座中使用。我的老师不能回答这个问题。因此,我希望社区能够提供帮助。@SethTisue为什么困难?我的问题(见编辑)中描述的方法如何?这是一个好问题,但它不是真正的主题。我建议使用Scala邮件列表