我刚刚开始学习Scala,我注意到:
在很多地方使用过。大多数情况下,:
用法是有道理的,例如在参数名称或方法声明之后。但是,以下用法让我感到困惑:
val a = Seq[String]("a", "b")
a :+ "c"
或
def myMethod(varargs: String*) {
// ...
}
val a = Seq[String]("a", "b", "c")
myMethod(a:_*)
:
在这些情况下究竟做了什么?为什么我不能直接致电a._*
?
答案 0 :(得分:4)
您要问的两个用法是两个完全不同的案例。
a :+ "c"
:
在这里并不意味着什么;它是名为:+
的方法的一部分,它将一个元素附加到Seq
。
myMethod(a:_*)
在这里,你有一个方法myMethod
,它接受可变数量的参数。您想使用Seq
来填充参数; : _*
表示您想要这样做(而不是将Seq
本身作为方法的第一个参数传递)。
请注意,如果方法名称以<{1}}结束,则:
具有特殊含义(如果它与第一个示例中的:
一样开头)。在这种情况下,该方法将是右关联;这意味着该方法将在右侧的东西上调用,左侧的东西作为参数,而不是反向。
答案 1 :(得分:2)
告诉编译器您希望将序列拆分并作为单独的参数提供。
def myMethod(varargs: String*) = {
// varargs is a Seq
val x:Seq[String] = varargs
}
// Calling it is different
myMethod("a", "b")
// To call using a seq, you need to signal the compiler
myMethod(mySeqOfString: _*)
// They choose the `:` because this would be valid too:
myMethod(myString: String)
在您给a :+ "c"
的另一个示例中,:
具有不同的含义。它只是方法名称的一部分。他们可以将其命名为append
,但他们选择:+
。原因是:
中的+:
具有特殊含义:bind to the right
。这允许"c" +: a
。因此,为了保持一致性,他们可能选择:+
作为追加,+:
作为前置。
答案 2 :(得分:0)
:+
是Seq[A]
上的一种方法,它将给定的项目附加到序列中。
在第二个示例中,myMethod(a : _*)
a : _*
用于将序列作为变量参数列表传递给myMethod
函数。
答案 3 :(得分:0)
Scala中结肠的重要性因环境而异。
如您所知,它将声明中的标识符与其类型分开。
它也可以作为涉及序列的运算符的一部分出现。
由于Scala中的运算符实际上只是一个方法,因此它在此处的使用是任意的,但您可以依赖于冒号位于指向序列的二元运算符一侧的约定。
所以你的例子
a :+ "c"
将字符串"c"
追加到a
字符串序列,而
"c" +: a
将字符串添加到序列中。 (或者,更确切地说,在不可变序列的情况下,返回由前置/后置操作产生的新序列。请参阅documentation)
你的最后一个例子
myMethod(a: _*)
(我必须查找感谢教学!请参阅documentation)告诉编译器将序列扩展为varargs(而不是单个参数)。