#list #scala #recursion #pattern-matching
#Список #scala #рекурсия #сопоставление с образцом
Вопрос:
У меня здесь проблема из 99 проблем scala (http://aperiodic.net/phil/scala/s-99/p03.scala ), что я пытаюсь понять, как это работает. Я довольно новичок в Scala. Я смог выполнить эту задачу с помощью аналогичного решения, используя сопоставление с образцом и рекурсию, однако мой не рассматривал список в сопоставлении. Мой код приведен ниже:
def nth[A](k: Int, l: List[A]): A = k match {
case 0 => l.head
case _ => nth(k-1, l.drop(1))
}
и это, казалось, сделало свое дело. Однако нет проверки ошибок, если список равен нулю. Решение 99 проблем scala обеспечивает:
def nthRecursive[A](n: Int, ls: List[A]): A = (n, ls) match {
case (0, h :: _ ) => h
case (n, _ :: tail) => nthRecursive(n - 1, tail)
case (_, Nil ) => throw new NoSuchElementException
}
Чего я не понимаю, так это
case(0, h:: _ )
и
case(n, _ :: tail)
Что здесь делает автор? Я понимаю :: добавляет все, что находится слева, к началу того, что справа, но я точно не уверен, что происходит. Кто-нибудь может меня просветить?
Спасибо!
Ответ №1:
Оператор :: используется для извлечения заголовка и остальной части списка (хвоста).
Здесь:
case(0, h :: _ )
только заголовок имеет значение, поэтому хвост не получает ссылку.
И здесь:
case(n, _ :: tail)
имеет значение только хвост, поэтому заголовок не получает ссылку.
Вы также можете использовать:
case(0, head :: tail)
case(n, head :: tail)
(т. е. Предоставление ссылки на обе части) и получение точно такого же результата.
Комментарии:
1. Итак, в основном, поскольку _ является шаблоном (соответствует чему-либо), но на самом деле не хранит что-то, совпадение будет хранить только head и игнорировать tail? Это интересно. Интересно, почему этот синтаксис не описан в документации по списку на веб-сайте Scala.
Ответ №2:
По сути, это выражение сопоставления с образцом. Вот почему сопоставление шаблонов Scala настолько мощно, поэтому мы можем отбросить некоторые тяжелые шаблоны посетителей, такие как Java (из этой темы).
Простой пример:
case class User(name: String, age: Int)
def doStuff(user: User) = user match {
case User(_, age) if age > 100 => println("Impossible!")
case User(name, _) => println("hello " name)
}
В этом случае _ :: tail просто означает, что я хочу получить ссылку на хвост.