Раздражает, что некоторые из наиболее заметных и удивительных особенностей Scala имеют такую сложность прямо под поверхностью. Итак, рассмотрим эту простую строку:
val (head :: tail): ::[Int] = 1 :: Nil
Каждое из трех мест, где появляется ::
, относится к другому ::
и другому механизму в Scala. Давайте рассмотрим каждый из них по порядку.
head :: tail
То, что здесь происходит, это сопоставление с шаблоном , точно так же, как можно увидеть с помощью case
операторов. Сопоставление с образцом может появляться в val
назначениях, в левой части <-
в for
пониманиях и в case
утверждениях.
Итак, как происходит это конкретное сопоставление с образцом? Что ж, всякий раз, когда шаблон имеет формат a b c
, Scala переводит его в b(a, c)
, который затем переводится в вызовы unapply
или unapplySeq
для объекта b
.
Итак, ::
в val (head :: tail)
относится к объекту ::
(определенному через case class
).
: ::[Int]
Это объявление типа, поэтому ::[Int]
это тип. ::
сам по себе является классом, а также конструктором типов (поскольку он создает типы по заданному параметру типа - ::[Int]
- это один тип, ::[String]
- другой тип и т. Д.). Это также подкласс List
, который имеет только два подкласса: ::
и класс синглтона Nil
.
Это объявление излишне, и, вообще говоря, вряд ли когда-либо будет использоваться ::
в качестве типа или класса. Я показываю это здесь в основном для полноты.
1 :: Nil
Здесь ::
- это метод. Это метод List
, поэтому, поскольку Nil
является List
, а 1
- нет, он должен принадлежать Nil
(или быть доступным через неявное преобразование).
Следует отметить, что методы, заканчивающиеся на :
, при использовании в нотации инфиксного оператора связываются справа, а не слева. Или, другими словами, a :: b
эквивалентно b.::(a)
.
Этот механизм используется редко и, я подозреваю, в основном сделан для того, чтобы сделать традиционные алгоритмы списка fp более знакомыми программистам, использующим fp. Он используется в некоторых других местах стандартной библиотеки Scala и вне ее.
Например, в Scala 2.8 теперь есть +:
, который служит для той же цели, что и ::
, но определен для всех Seq
. Он отражается :+
, который добавляет элементы, и чей :
не служит никакой другой цели, кроме устранения неоднозначности его с +
, который перегружен для объединения строк.