Подтвердить что ты не робот

Почему класс scala list named::

Почему реализована реализация списка scala с именем:: и не имя класса? Есть ли какое-то особое значение?

4b9b3361

Ответ 1

Это будет работать с сопоставлением с образцом. У вас есть что-то, называемое шаблонами операторов Infix, где шаблон p op q эквивалентен шаблону конструктора или экстрактора op(p, q).

Таким образом, класс case :: определяет конструктор ::(head, tail). Это позволяет вам выполнить следующие действия:

list match {
  case ::(head, tail) =>
}

Но с шаблоном оператора infix вы можете написать более знакомый синтаксис:

list match {
  case head :: tail =>
}

Обратите внимание, что поиск stackoverflow в "[ scala] шаблоне инфикс-оператора" возвращает похожие вопросы и дополнительные примеры использования шаблона.

Ответ 2

Связанный список состоит из двух случаев: ячейки cons (с головой и хвостом) и пустого списка. Эти случаи называются :: и Nil соответственно в Scala, как на других языках с наследием ML. В неизменной реализации наиболее естественная кодировка выглядит примерно так:

sealed trait List[+A]

case class Cons[+A](head: A, tail: List[A]) extends List[A]
case object Nil extends List[Nothing]

Это работает отлично, и в этом нет ничего плохого. Вы можете определить метод :: на List (или prepend, если хотите), и все будет работать точно так, как вы ожидали. В этом случае "конкретная реализация" List будет Cons, хотя технически оба Cons и Nil являются конкретными реализациями.

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

def sum(xs: List[Int]): Int = xs match {
  case Cons(hd, tl) => hd + sum(tl)
  case Nil => 0
}

Это немного уродливо. Нам действительно нужно иметь возможность использовать оператор :: в нашем шаблоне так же, как мы его используем при построении списка изначально. Вот почему класс Cons имеет имя ::.

Определив класс case из двух параметров, мы в основном говорим Scala, что хотим, чтобы он позволил нам использовать этот класс case в качестве экстрактора инфикс в сопоставлении с образцом. Задний двоеточие делает этот экстрактор прав-ассоциативным, давая нам ожидаемый синтаксис:

sealed trait List[+A]

case class ::[+A](head: A, tail: List[A]) extends List[A]
case object Nil extends List[Nothing]

def sum(xs: List[Int]): Int = xs match {
  case hd :: tl => hd + sum(tl)
  case Nil => 0
}

Вот почему любой экземпляр List с содержимым будет экземпляром класса ::, так как это непустая реализация List.

Ответ 3

Это стандартное имя оператора cons, который добавляет элемент в список.