Что делает `: _ *` (подчеркивание двоеточия) в Scala?

137

У меня есть такой код из этого вопроса:

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, а потом? Что делает : _*?

  • 54
    Большое спасибо за добавление (знак подчеркивания двоеточия) к названию!
Теги:
pattern-matching

2 ответа

109
Лучший ответ

Он "отображает" 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 Это не имеет cutesy-name в SLS, но вот подробности. Важно то, что он изменяет, как Scala связывает аргументы с методом с повторяющимися параметрами (как указано выше с Node*).

Аннотации типа _* описаны в разделе "4.6.2 Повторяющиеся параметры" SLS.

Последний параметр значения секции параметров может быть удовлетворен "*", например. (..., x: T *). Тип такого повторяющегося параметра внутри метода тогда   тип последовательности scala.Seq [T]. Методы с повторяющимися параметрами T * принимают   переменное количество аргументов типа T. То есть, если метод m с типом   (p1: T1,..., pn: Tn, ps: S *) U применяется к аргументам (e1,..., ek), где k >= n, тогда   m принимает в этом приложении тип (p1: T1,..., pn: Tn, ps: S,..., ps0S) U,   с k ¡n вхождениями типа S, где любые имена параметров за пределами ps   свежий. Единственное исключение из этого правила - если последний аргумент отмечен как   аргумент последовательности с помощью аннотации типа _ *. Если m применяется к аргументам (e1,..., en, e0: _ *), то тип m в этом приложении принимается как   (p1: T1,..., pn: Tn, ps: scala.Seq [S])

  • 3
    Нам нравится называть это «оператором Smooch», хотя на самом деле это не оператор :)
  • 0
    В Python это называется распаковка
Показать ещё 1 комментарий
66
  • child ++ newChild - последовательность
  • : - тип ascription, подсказка, которая помогает компилятору понять, какой тип имеет это выражение
  • _* - заполнитель, принимающий любое значение + оператор vararg

child ++ newChild : _* расширяет Seq[Node] до Node* (сообщает компилятору, что мы скорее работаем с varargs, чем последовательность). Особенно полезно для методов, которые могут принимать только varargs.

  • 0
    Не могли бы вы написать больше о "тип надписи"? Что это и как это работает?
  • 9
    stackoverflow.com/questions/2087250/...

Ещё вопросы

Сообщество Overcoder
Наверх
Меню