Ответ 1
Это раздражает, что некоторые из наиболее видимых и удивительных функций 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
(или быть доступен через неявное преобразование).
Механизм примечания здесь состоит в том, что методы, заканчивающиеся на :
, при использовании в нотации оператора infix, связывают справа, а не влево. Или, другими словами, a :: b
эквивалентно b.::(a)
.
Этот механизм редко используется и, как я подозреваю, в основном делал традиционные алгоритмы списка fp более знакомыми для программистов, используемых для fp. Он используется в нескольких других местах в стандартной библиотеке Scala и из него.
В Scala 2.8, например, теперь есть +:
, который выполняет ту же цель ::
, но определен для всех Seq
. Он отражается :+
, который добавляет элементы и чей :
не имеет никакой цели, кроме устранения его неоднозначности из +
, который перегружен для объединения строк.