Scala 错误或功能?大写字母变量的多重赋值错误

Posted

技术标签:

【中文标题】Scala 错误或功能?大写字母变量的多重赋值错误【英文标题】:Scala bug or feature? Multiple assignment error with capital letter variables 【发布时间】:2016-07-21 22:48:50 【问题描述】:

假设函数r 返回五个值的元组。

scala> def r = (1,2,3,4,5)
r: (Int, Int, Int, Int, Int)

当我从r 分配返回值时,出现大写字母变量错误。

scala> val (a,b,c,d,E) = r
<console>:13: error: not found: value E
       val (a,b,c,d,E) = r
                    ^

如果我不使用大写字母,则不会发生错误。

scala> val (a,b,c,d,e) = r
a: Int = 1
b: Int = 2
c: Int = 3
d: Int = 4
e: Int = 5

但是,我可以使用单个分配来分配大写字母变量。

scala> val Q = 10
Q: Int = 10

这是 Scala 的错误还是特性?

【问题讨论】:

【参考方案1】:

这是一个功能......虽然不是很理想。

当你做val (a,b,c) = tuple时,其实是模式匹配:

tuple match 
   case (a,b,c) => ...

现在,上面的语句使用unapply 从元组中提取三个值,并将它们分配给a、b 和c。但是这个:

tuple match 
   case (1, 2, 3) => ...

做一些不同的事情。它从元组中提取三个值,并将它们与左侧的三个值进行比较。如果你想匹配一个变量怎么办:

val foo = 1
val bar = 2
val bat = 3

tuple match 
  case(foo, bar, bat) => ...

这不起作用:这种情况与第一种情况完全相同,并且会做同样的事情:它将元组中的值提取到三个(新)局部变量中,没有任何匹配。但是如果你想匹配变量呢?如何解决这个问题?有两种方法:您可以将变量名称括在反引号中,或者使名称以大写字母开头:

  val Foo = 1
  val bar = 2
  var baz = 3

  tuple match  
    case(Foo, `bar`, `bat`) => ...
  

总结一下:tuple match case (foo, _) =&gt; 表示“从元组中提取第一个元素并分配给一个新变量footuple match case (Foo, _) 表示“如果元组的第一个元素等于现有变量Foo"。 “分配”遵循相同的逻辑(因为它们并不是真正的“分配”,而是模式匹配的另一种语法),因此,当您说val (a,b,c,d,E) = r 时,它的意思是“将r 的前四个元素分配给新变量,并将最后一个元素与现有变量 E" 匹配。但是E不存在,所以报错。

【讨论】:

有什么办法可以解决这个问题并执行 OP 想要做的事情,将值分配给以大写字母开头的变量?喜欢反引号的反义词吗? @LuigiPlinge 不是我知道的...除了val (a, b) = tuple; val B = b【参考方案2】:

它被称为稳定标识符。因此,每当您在进行模式匹配(在这种情况下发生)时使用大写字母作为变量名(或变量名的开头)时,编译器都会认为这是一个常量值,因此会进入行为(比较两个值 E 和 5 而不是将 5 分配给 E)。

例子:

val (a,b,c,d,extsom) = r这会起作用。

val (a,b,c,d,Extsom) = r这不会。

【讨论】:

以上是关于Scala 错误或功能?大写字母变量的多重赋值错误的主要内容,如果未能解决你的问题,请参考以下文章

scala中非元组的多重赋值

Python基础

对象变量和常量

全局变量重复定义,fatal error LNK1169: 找到一个或多个多重定义的符号

lua基础简介

分离式编译时 链接器工具错误 (一个变量被定义一次或多次)