Scala и:: объект

Я нырял в scala, и до сих пор люблю его. Я обойдусь с шаблонами совпадения и классами case, и следующее меня несколько озадачило. Я знаю, что он делает, но я хочу точно понять, что происходит.

var list = List(2,3,4)
1::list

Если я догадываюсь в своем понимании. Тогда:: представляет объект case. Если так, то мой вопрос:

как я "оставил применение" его к 1? а не:: как метод 1. В принципе, кто-то может немного раскрыть это утверждение 1:: list отдельно, показывая, что на самом деле происходит (то есть, какие методы вызывают на каком объекте)

Спасибо

Ответы

Ответ 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. Он отражается :+, который добавляет элементы и чей : не имеет никакой цели, кроме устранения его неоднозначности из +, который перегружен для объединения строк.

Ответ 2

Имя оператора, заканчивающееся на :, связывается вправо. :: [A] действительно является case class и подклассом List[A], как это видно в Scala ссылке API. :: - также метод, действующий на свой правый аргумент, список, принимающий его левый операнд в качестве аргумента и возвращающий ::[A].

Итак, в вашем примере метод :: вызывается в list с 1 в качестве аргумента. Это создает объект типа :: [Int] с аргументами 1 и list.

Ответ 3

Очень быстрый ответ. Метод:: вызывается в списке с параметром 1.

Любое имя метода (и да,:: - метод), который заканчивается двоеточием, работает в правом операнде.

Ответ 4

Чтобы добавить дополнительную информацию к другим ответам:

:: является одновременно подклассом 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)

который в основном реализуется в терминах первого.

Таким образом, за этим нет глубоких теоретических основ, просто имейте в виду правило о методах, заканчивающихся на :.

Ответ 5

Мое понимание:: (оператора cons) заключается в том, что оно используется таким образом, поскольку добавление элемента в список (технически, создание нового списка с новым элементом, предшествующим старому списку) имеет значение O (1), тогда как добавление его было бы O (N). Это эффективность...