Scala и объект::
Я нырял в скалу, и до сих пор мне это очень нравится. Я перехожу к сопоставлению с образцом и кейсам, и следующее несколько озадачило меня. Я знаю, что он делает, но я хочу точно понять, что происходит
var list = List(2,3,4)
1::list
Если я прав в моем понимании до сих пор. Затем:: представляет объект case. Если так, то мой вопрос:
как я "оставил заявку" на 1? вместо того, чтобы:: быть методом 1. По сути, кто-то может несколько отделить это утверждение 1:: list, показывая, что на самом деле происходит (т.е. какие методы вызываются для какого объекта)
Спасибо
5 ответов
Раздражает, что некоторые из самых заметных и удивительных особенностей Scala имеют такую сложность прямо под поверхностью. Итак, рассмотрим эту простую строку:
val (head :: tail): ::[Int] = 1 :: Nil
Каждое из трех мест, где ::
Похоже, относится к другому ::
и другой механизм в Scala. Давайте рассмотрим каждый из них по порядку.
head :: tail
То, что здесь происходит, - это сопоставление с образцом, точно так же, как case
заявления. Сопоставление с образцом может появиться на val
назначения, на левой стороне <-
в for
понимание и на case
заявления.
Итак, как происходит это конкретное сопоставление с образцом? Хорошо, когда шаблон в формате a b c
Скала переводит это в 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
, Это отражено :+
, который добавляет элементы, и чей :
не служит никакой иной цели, кроме устранения неоднозначности +
, который перегружен для объединения строк.
Имя оператора, оканчивающееся на :
связывает вправо. :: [A]
действительно case class
и подкласс List[A]
, как видно из справочника по Scala API. ::
также метод, работающий со своим правым аргументом, списком, принимающим левый операнд в качестве аргумента и возвращающим ::[A]
,
Итак, в вашем примере, метод ::
называется на list
с 1
в качестве аргумента. Это создает объект типа :: [Int]
с аргументами 1
а также list
,
Очень быстрый ответ. Метод:: вызывается из списка с параметром 1.
Любое имя метода (и да,:: это метод), заканчивающееся двоеточием, работает с правым операндом.
Я понимаю, что:: (оператор "cons") заключается в том, что он используется таким образом, потому что добавление элемента в список (технически, создание нового списка с новым элементом, добавленным к старому списку) имеет значение O(1) в то время как добавление было бы O(N). Это вещь эффективности...
Чтобы добавить дополнительную информацию к другим ответам:
::
это подкласс List
final case class ::[B](private var hd: B, private[scala] var tl: List[B]) extends List[B] { ... }
и метод на List
def ::[B >: A] (x: B): List[B] = new scala.collection.immutable.::(x, this)
который в основном реализован в терминах первого.
Так что за этим нет глубоких теоретических основ, просто имейте в виду правило о методах, заканчивающихся на :
,