Что делает`: * ' (colon underscore star) в Scala?
у меня есть следующий фрагмент кода этот вопрос:
def addChild(n: Node, newChild: Node) = n match {
case Elem(prefix, label, attribs, scope, child @ _*) => Elem(prefix, label, attribs, scope, child ++ newChild : _*)
case _ => error("Can only add children to elements!")
}
все в нем довольно ясно, кроме этой части:child ++ newChild : _*
что он делает?
Я так понимаю есть Seq[Node]
соединяется с другой Node
, а потом? Что значит : _*
делать?
3 ответа:
это "знаки"1 последовательности.
посмотрите на подпись конструктора
new Elem(prefix: String, label: String, attributes: MetaData, scope: NamespaceBinding, child: Node*)
, которая называется
new Elem(prefix, label, attributes, scope, child1, child2, ... childN)
но здесь есть только последовательность, а не
child1
,child2
и т. д. таким образом, это позволяет использовать результирующую последовательность в качестве входных данных для конструктора.удачи в кодировании.
1 у этого нет симпатичного имени в SLS, но вот подробности. Главное, чтобы получить это что это меняет, как Scala связывает аргументы с методом с повторяющимися параметрами (как обозначается с
Node*
выше).The
_*
тип аннотации рассматривается в разделе" 4.6.2 повторные параметры " SLS.последнее значение параметра раздела параметров может быть суффиксом"*", например (..., x:T *). Тип такого повторяющегося параметра внутри метода тогда последовательность типа scala.Seq[T]. Методы с повторением параметры T * take переменное число аргументов типа T . То есть, если метод m с типом (p1 : T1, . . . , pn : Tn,ps: S*)U применяется к аргументам (e1, . . . , ek) где k >= n, то m принимается в этом приложении, чтобы иметь тип (p1: T1, . . . ру : ТН зы : с . . . , ps0S) U, с K ¡ N вхождений типа S, где любые имена параметров за пределами ps являются свежий. единственное исключение из этого правила, если последний аргумент помечен как аргумент последовательности через _* Аннотация типа. Если M выше применяется к аргументам (e1,. . . , en, e0:_*), то тип m в этом приложении принимается равным (p1 : T1, . . . , pn :Tn,ps: scala.Seq[S])
child ++ newChild
последовательности:
- Type ascription, подсказка, которая помогает компилятору понять, какой тип имеет это выражение_*
- заполнитель, принимающий любое значение + оператор vararg
child ++ newChild : _*
расширяетSeq[Node]
доNode*
(говорит компилятору, что мы скорее работаем с varargs, чем с последовательностью). Особенно полезно для методов, которые могут принимать только varargs.
все вышеприведенные ответы выглядят великолепно, но просто нужен образец, чтобы объяснить это . Вот это :
val x : Seq[Seq[Int]] = Seq(Seq(1),Seq(2)) def f(arg: Seq[Any]*) : Int = { arg.length } f(x) //1 as x is taken as single arg f(x:_*) // 2 as x is "unpacked" as a Seq[Any]*
Итак, теперь мы знаем, что
:_*
do-это сообщить компилятору: пожалуйста, распакуйте этот аргумент и свяжите эти элементы с параметром vararg в вызове функции, а не принимайте x в качестве одного аргумента .Итак, в двух словах,
:_*
убрать двусмысленность, когда аргумент передать параметр с переменным числом аргументов.