我有以下代码:
val text = "some text goes here"
val (first, rest) = text.splitAt(4)
println(first + " *" + rest)
工作正常。
但是,我想要两个案例,定义"第一个"和"休息"外面,像这样:
val text = "some text goes here"
var (first, rest) = ("", "")
if (text.contains("z")) {
(first, rest) = text.splitAt(4)
} else {
(first, rest) = text.splitAt(7)
}
println(first + " *" + rest)
但这给了我一个错误:
scala> | <console>:2: error: ';' expected but '=' found.
(first, rest) = text.splitAt(4)
为什么要做错误(首先,休息)= text.splitAt(4)但不要做val(第一次,休息)= text.splitAt(4)?我该怎么办?
编辑:无法重新分配val,更改为var。同样的错误
答案 0 :(得分:15)
Serj的回答提供了一种更好的方式来写这个,但是为了回答你关于为什么你的第二个版本不起作用的问题,你可以转到Scala specification,这可以区分变量定义和分配。
来自“4.2变量声明和定义”:
变量定义也可以有一个模式(§8.1) 左手边。变量定义
var p = e
,其中p
是 模式以外的简单名称或名称后跟冒号和 type以val p = e
的相同方式(第4.1节)进行扩展,但p
中的自由名称是作为可变变量引入的,而不是值。
来自“6.15作业”:
对简单变量
x = e
的赋值的解释取决于 关于x
的定义。如果x
表示一个可变变量,那么 赋值将x
的当前值更改为结果 评估表达式e
。
(first, rest)
这里是一个模式,而不是一个简单的变量,因此它适用于变量定义,但不适用于赋值。
答案 1 :(得分:13)
首先val
是不可变的,因此您无法重新分配它。其次,if
与Scala中的所有控制结构一样,可以返回一个值。所以,你可以这样做:
val text = "some text goes here"
val (first, rest) = if (text.contains("z")) text.splitAt(4) else text.splitAt(7)
println(first + " *" + rest)
答案 2 :(得分:9)
SerJ de SuDDeN的答案是绝对正确的,但更详细的一些细节为什么你提到的代码以它的工作方式工作。
val (a, b) = (1, 2)
被称为模式匹配表达式的提取器。右侧的值与左侧的提取器匹配。这可以在Scala中的任何地方完成,并且可以具有不同的面。例如,List上的模式匹配可能类似于
scala> val head :: tail = 1 :: 2 :: 3 :: Nil
head: Int = 1
tail: List[Int] = List(2, 3)
在右侧,::
- 符号是类List的方法,它为元素添加元素。在左侧,::
- 符号是类::
的提取器,是List的子类。
其他一些地方可以是理解
scala> for ((a, b) <- (1 to 3) zip (4 to 6)) println(a+b)
5
7
9
或具有更高阶方法的等效符号
scala> (1 to 3) zip (4 to 6) foreach { case (a, b) => println(a+b) }
5
7
9