Scala '::' оператор, как это работает?

В Scala я могу сделать caseclass, case class Foo(x:Int), и затем помещенный это в список как так:

List(Foo(42))

Теперь, ничто странное здесь. Следующее является странным для меня. Оператор :: функция в списке, правильно? С любой функцией с одним аргументом в Scala я могу назвать его с инфиксной нотацией. Пример 1 + 2 функция (+) на объекте Int. Класс Foo Я просто определил, не имеет :: оператор, поэтому как следующее возможно?

Foo(40) :: List(Foo(2))

В Scala 2.8 RC1 я получаю следующий вывод от интерактивной подсказки:

scala> case class Foo(x:Int)
defined class Foo

scala> Foo(40) :: List(Foo(2))
res2: List[Foo] = List(Foo(40), Foo(2))

Я могу пойти и использовать его, но каково объяснение?

53
задан nbro 2 April 2017 в 05:44
поделиться

4 ответа

Из спецификации:

6.12.3 Инфиксные операции Инфиксный оператор может быть произвольным идентификатором. Инфиксные операторы имеют предшествование и ассоциативность, которые определяются следующим образом.

...

Ассоциативность оператора определяется последним символом. Операторы, заканчивающиеся двоеточием ':' являются право-ассоциативными. Все остальные операторы являются лево-ассоциативными.

Вы всегда можете увидеть, как эти правила применяются в Scala, распечатав программу после того, как она прошла через фазу 'typer' компилятора:

scala -Xprint:typer -e "1 :: Nil"

val r: List[Int] = {
  <synthetic> val x$1: Int = 1;
  immutable.this.Nil.::[Int](x$1)
};
48
ответ дан 7 November 2019 в 08:38
поделиться

Он заканчивается : . И это признак того, что эта функция определена в классе справа (здесь в классе List ).

Итак, это List (Foo (2)) .: :( Foo (40)) , а не Foo (40) .: :( List (Foo (2))) в вашем примере.

21
ответ дан 7 November 2019 в 08:38
поделиться

Класс Foo , который я только что определил, не имеет оператора :: , поэтому как возможно следующее:

Foo (40) :: List (Foo (2))

Если имя метода заканчивается двоеточием (: ), метод вызывается для правого операнда , который является случай здесь. Если имя метода не заканчивается двоеточием, метод вызывается для левого операнда. Например, a + b , + вызывается на a .

Итак, в вашем примере :: - это метод в правом операнде, который представляет собой список List .

16
ответ дан 7 November 2019 в 08:38
поделиться

В приведенных ответах отсутствует один аспект: поддержка :: в выражениях сопоставления с образцом:

List(1,2) match {
  case x :: xs => println(x + " " + xs)
  case _ => println("")
}

Определен класс :: :

final case class ::[B](private var hd: B, private[scala] var tl: List[B]) 

поэтому case: :( x, xs) даст тот же результат. Выражение case x :: xs работает, потому что экстрактор по умолчанию :: определен для класса case, и его можно использовать инфиксным.

18
ответ дан 7 November 2019 в 08:38
поделиться
Другие вопросы по тегам:

Похожие вопросы: