Оператор 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))

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

4 ответа

Решение

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

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

...

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

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

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

val r: List[Int] = {
  <synthetic> val x$1: Int = 1;
  immutable.this.Nil.::[Int](x$1)
};

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

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

Один из аспектов, отсутствующий в данных ответах, заключается в том, что :: в выражениях сопоставления с образцом:

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 и может быть использован infix.

Класс Foo Я только что определил, не имеет :: оператор, так как это возможно:

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

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

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

Другие вопросы по тегам