在 Scala 中声明多个变量
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1981748/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Declaring multiple variables in Scala
提问by Xavi
I'd like to use valto declare multiple variable like this:
我想用val这样的方式声明多个变量:
val a = 1, b = 2, c = 3
But for whatever reason, it's a syntax error, so I ended up using either:
但无论出于何种原因,这是一个语法错误,所以我最终使用了:
val a = 1
val b = 2
val c = 3
or
或者
val a = 1; val b = 2; val c = 3;
I personally find both options overly verbose and kind of ugly.
我个人认为这两个选项都过于冗长且有点丑陋。
Is there a better option?
有更好的选择吗?
Also, I know Scala is very well thought-out language, so why isn't the val a = 1, b = 2, c = 3syntax allowed?
另外,我知道 Scala 是经过深思熟虑的语言,那么为什么不允许使用val a = 1, b = 2, c = 3语法?
回答by Daniel C. Sobral
The trivial answer is to declare them as tuples:
简单的答案是将它们声明为元组:
val (a, b, c) = (1, 2, 3)
What might be interesting here is that this is based on pattern matching. What is actually happens is that you are constructing a tuple, and then, through pattern matching, assigning values to a, band c.
这里可能有趣的是,这是基于模式匹配。实际发生的情况是您正在构造一个元组,然后通过模式匹配为a、b和分配值c。
Let's consider some other pattern matching examples to explore this a bit further:
让我们考虑一些其他模式匹配示例来进一步探讨这一点:
val DatePattern = """(\d{4})-(\d\d)-(\d\d)""".r
val DatePattern(year, month, day) = "2009-12-30"
val List(rnd1, rnd2, rnd3) = List.fill(3)(scala.util.Random.nextInt(100))
val head :: tail = List.range(1, 10)
object ToInt {
def unapply(s: String) = try {
Some(s.toInt)
} catch {
case _ => None
}
}
val DatePattern(ToInt(year), ToInt(month), ToInt(day)) = "2010-01-01"
Just as a side note, the rndexample, in particular, may be written more simply, and without illustrating pattern matching, as shown below.
作为旁注,该rnd示例尤其可以写得更简单,并且不说明模式匹配,如下所示。
val rnd1, rnd2, rnd3 = scala.util.Random.nextInt(100)
回答by Daniel Spiewak
Daniel's answer nicely sums up the correct way to do this, as well as why it works. Since he already covered that angle, I'll attempt to answer your broader question (regarding language design)...
Daniel 的回答很好地总结了执行此操作的正确方法,以及它的工作原理。由于他已经涵盖了这个角度,我将尝试回答您的更广泛的问题(关于语言设计)......
Wherever possible, Scala strives to avoid adding language features in favor of handling things through existing mechanisms. For example, Scala doesn't include a breakstatement. However, it's almost trivial to roll one of your own as a library:
在可能的情况下,Scala 努力避免添加语言特性,而是通过现有机制处理事物。例如,Scala 不包含break语句。但是,将自己的一个作为库滚动几乎是微不足道的:
case object BreakException extends RuntimeException
def break = throw BreakException
def breakable(body: =>Unit) = try {
body
} catch {
case BreakException => ()
}
This can be used in the following way:
这可以通过以下方式使用:
breakable {
while (true) {
if (atTheEnd) {
break
}
// do something normally
}
}
(note:this is included in the standard library for Scala 2.8)
(注意:这包含在 Scala 2.8 的标准库中)
Multiple assignment syntaxes such as are allowed by languages like Ruby (e.g. x = 1, y = 2, z = 3) fall into the category of "redundant syntax". When Scala already has a feature which enables a particular pattern, it avoids adding a new feature just to handle a special case of that pattern. In this case, Scala already has pattern matching (a general feature) which can be used to handle multiple assignment (by using the tuple trick outlined in other answers). There is no need for it to handle that particular special case in a separate way.
诸如Ruby(例如x = 1, y = 2, z = 3)之类的语言所允许的多重赋值语法属于“冗余语法”的范畴。当 Scala 已经具有启用特定模式的功能时,它会避免添加新功能只是为了处理该模式的特殊情况。在这种情况下,Scala 已经具有模式匹配(一个通用功能),可用于处理多重赋值(通过使用其他答案中概述的元组技巧)。它不需要以单独的方式处理特定的特殊情况。
On a slightly different aside, it's worth noting that C's (and thus, Java's) multiple assignment syntax is also a special case of another, more general feature. Consider:
稍微不同的是,值得注意的是,C(以及 Java 的)多重赋值语法也是另一个更通用的特性的特例。考虑:
int x = y = z = 1;
This exploits the fact that assignment returns the value assigned in C-derivative languages (as well as the fact that assignment is right-associative). This is not the case in Scala. In Scala, assignment returns Unit. While this does have some annoying drawbacks, it is more theoretically valid as it emphasizes the side-effecting nature of assignment directly in its type.
这利用了赋值返回 C 派生语言中赋值的事实(以及赋值是右结合的事实)。这在 Scala 中并非如此。在 Scala 中,赋值返回Unit. 虽然这确实有一些令人讨厌的缺点,但它在理论上更有效,因为它直接在其类型中强调了赋值的副作用性质。
回答by akauppi
I'll add one quirk here, because it hit myself and might help others.
我会在这里添加一个怪癖,因为它击中了我自己并且可能会帮助其他人。
When using pattern matching, s.a. in declaring multiple variables, don't use Capital names for the variables. They are treated as names of classes in pattern matching, and it applies here as well.
使用模式匹配时,sa 在声明多个变量时,不要对变量使用大写名称。它们在模式匹配中被视为类的名称,在这里也适用。
val (A,B)= (10,20) // won't work
println(A)
Error message does not really tell what's going on:
错误消息并没有真正说明发生了什么:
src/xxx.scala:6: error: not found: value A val (A,B)= (10,20) ^ src/xxx.scala:6: error: not found: value B val (A,B)= (10,20) ^ src/xxx.scala:7: error: not found: value A println(A) ^
src/xxx.scala:6: error: not found: value A val (A,B)= (10,20) ^ src/xxx.scala:6: error: not found: value B val (A,B)= (10,20) ^ src/xxx.scala:7: error: not found: value A println(A) ^
I thought `-ticking would solve the issue but for some reason does not seem to (not sure, why not):
我认为 `-ticking 会解决这个问题,但由于某种原因似乎没有(不确定,为什么不):
val (`A`,`B`)= (10,20)
println(A)
Still the same errors even with that.
即使这样,仍然存在相同的错误。
Please comment if you know how to use tuple-initialization pattern with capital variable names.
如果您知道如何使用带有大写变量名称的元组初始化模式,请发表评论。
回答by smartnut007
If all your variables are of the same type and take same initial value, you could do this.
如果你所有的变量都是相同的类型并采用相同的初始值,你可以这样做。
val a, b, c: Int = 0;
回答by Joe
It seems to work if you declare them in a tuple
如果你在元组中声明它们似乎有效
scala> val (y, z, e) = (1, 2, 45)
y: Int = 1
z: Int = 2
e: Int = 45
scala> e
res1: Int = 45
Although I would probably go for individual statements. To me this looks clearer:
虽然我可能会选择个人陈述。对我来说,这看起来更清楚:
val y = 1
val z = 2
val e = 45
especially if the variables are meaningfully named.
特别是如果变量被有意义地命名。

