Разложение совпадений по скале на инфиксный оператор - PullRequest
9 голосов
/ 20 июня 2009

Я пытаюсь понять реализацию List s в 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)?

Ответы [ 3 ]

13 голосов
/ 21 июня 2009

Ответ Джея Конрада почти верен. Важно то, что где-то есть объект с именем ::, который реализует метод unapply, возвращая тип Option[(A, List[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. Однако, как показывает приведенный выше пример, он не имеет , чтобы быть классом дел вообще.

7 голосов
/ 20 июня 2009

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

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

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

a match {
  case x %%% y => x + y
}
2 голосов
/ 20 декабря 2010

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

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

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

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

См. Также Вопросы по классам случаев Scala

...