Разложение совпадений по скале на инфиксный оператор
-
06-07-2019 - |
Вопрос
Я пытаюсь понять реализацию 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