Разложение совпадений по скале на инфиксный оператор

StackOverflow https://stackoverflow.com/questions/1022218

Вопрос

Я пытаюсь понять реализацию List в Scala. В частности, я пытаюсь понять, как можно писать выражения совпадений, используя инфиксный оператор, например:

a match {
  case Nil => "An empty list"
  case x :: Nil => "A list without a tail"
  case x :: xs => "A list with a tail"
}

Каким образом выражение соответствия может быть x :: xs , а не List (x, xs) ?

Это было полезно?

Решение

Ответ Джея Конрада почти правильный. Важно то, что где-то есть объект с именем :: , который реализует метод unapply , возвращая тип Option [(A, Список [A])] . Thusly:

object :: {
  def unapply[A](ls: List[A]): Option[(A, A)] = {
    if (ls.empty) None
    else Some((ls.head, ls.tail))
  }
}

// case objects get unapply for free
case object Nil extends List[Nothing]

В случае :: и List этот объект происходит из-за того, что :: является классом case, который расширяет черту List . Однако, как показывает приведенный выше пример, он не должен быть классом case вообще.

Другие советы

Я считаю, что :: на самом деле является классом (который является подклассом List ), так что x :: xs в основном эквивалентно List (x, xs) .

Вы можете сделать это с другими классами дел, которые имеют имена операторов. Например:

case class %%%(x: Int, y: Int)

a match {
  case x %%% y => x + y
}
  

Как разрешить выражению совпадения быть x :: xs, а не List (x, xs)?

Чтобы ответить на этот вопрос:

  

Когда рассматривается как шаблон , инфикс   такая операция, как p op q , эквивалентна   в оп (р, q) . То есть инфикс   Оператор op рассматривается как    шаблон конструктора .

(Программирование в Scala, 1-е изд., стр. 331)

См. также вопросы о классах scala case

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top