scalabook

Форк
0
/
pattern-matching.md 
199 строк · 6.5 Кб

Сопоставление с образцом

Экстракторы

Экстракторы — это объекты, которые предоставляют метод unapply

или unapplySeq
:

def unapply[A](x: T)(implicit x: B): U
def unapplySeq[A](x: T)(implicit x: B): U

Экстракторы, предоставляющие метод unapply

, называются экстракторами с фиксированной арностью. Экстракторы, предоставляющие метод unapplySeq
, называются экстракторами с переменным числом параметров.

Экстракторы с фиксированной арностью

Экстракторы с фиксированной арностью предоставляют следующую подпись:

def unapply[A](x: T)(implicit x: B): U

Тип U

соответствует одному из следующих совпадений:

  • Логическое совпадение
  • Соответствие продукта

Или U

соответствует типу R
:

type R = {
def isEmpty: Boolean
def get: S
}

и S

соответствует одному из следующих совпадений:

  • одно совпадение
  • совпадение по имени

Первая форма unapply

имеет более высокий приоритет, а одиночное совпадение имеет более высокий приоритет, чем сопоставление на основе имени.

Использование экстрактора с фиксированной арностью применяется, если выполняется одно из следующих условий:

  • U = true
  • экстрактор используется в качестве соответствия продукта
  • U = Some[T]
    (для совместимости со Scala 2)
  • U <: R
    , а также U <: { def isEmpty: false }

Логическое совпадение

Пример:

object Even:
def unapply(s: String): Boolean = s.size % 2 == 0
"even" match
case s @ Even() => println(s"$s has an even number of characters")
case s => println(s"$s has an odd number of characters")
// even has an even number of characters

Соответствие продукта

Пример:

class FirstChars(s: String) extends Product:
def _1 = s.charAt(0)
def _2 = s.charAt(1)
// Not used by pattern matching: Product is only used as a marker trait.
def canEqual(that: Any): Boolean = ???
def productArity: Int = ???
def productElement(n: Int): Any = ???
object FirstChars:
def unapply(s: String): FirstChars = new FirstChars(s)
"Hi!" match
case FirstChars(char1, char2) =>
println(s"First: $char1; Second: $char2")
// First: H; Second: i

Одиночное совпадение

Пример:

class Nat(val x: Int):
def get: Int = x
def isEmpty = x < 0
object Nat:
def unapply(x: Int): Nat = new Nat(x)
5 match
case Nat(n) => println(s"$n is a natural number")
case _ => ()
// 5 is a natural number

Совпадение по имени

Пример:

object ProdEmpty:
def _1: Int = ???
def _2: String = ???
def isEmpty = true
def unapply(s: String): this.type = this
def get = this
"" match
case ProdEmpty(_, _) => ???
case _ => println("not ProdEmpty")
// not ProdEmpty

Экстракторы с переменным числом параметров

Экстракторы с переменным числом параметров предоставляют следующую сигнатуру:

def unapplySeq[A](x: T)(implicit x: B): U

Тип U

соответствует одному из следующих совпадений:

  • соответствие последовательности
  • соответствие последовательности продуктов

Или U

соответствует типу R
:

type R = {
def isEmpty: Boolean
def get: S
}

и S

соответствует одному из двух совпадений выше.

Соответствие последовательности имеет более высокий приоритет, чем соответствие последовательности продуктов.

Использование экстрактора с переменным числом параметров применяется, если выполняется одно из следующих условий:

  • экстрактор используется непосредственно как соответствие последовательности или соответствие продукта последовательности
  • U = Some[T]
    (для совместимости со Scala 2)
  • U <: R
    , а также U <: { def isEmpty: false }

Совпадение последовательности

Пример:

object CharList:
def unapplySeq(s: String): Option[Seq[Char]] = Some(s.toList)
"example" match
case CharList(c1, c2, c3, c4, _, _, _) =>
println(s"$c1,$c2,$c3,$c4")
case _ =>
println("Expected *exactly* 7 characters!")
// e,x,a,m

Соответствие последовательности продуктов

Пример:

class Foo(val name: String, val children: Int*)
object Foo:
def unapplySeq(f: Foo): Option[(String, Seq[Int])] =
Some((f.name, f.children))
def foo(f: Foo): Unit = f match
case Foo(name, x, y, ns*) =>
println(s"name = $name, x = $x, y = $y, ns = $ns")
case Foo(name, ns*) =>
println(s"name = $name, ns = $ns")
foo(new Foo("first", 2))
// name = first, ns = ArraySeq(2)
foo(new Foo("first", 2, 3))
// name = first, x = 2, y = 3, ns = ArraySeq()
foo(new Foo("first", 2, 3, 4))
// name = first, x = 2, y = 3, ns = ArraySeq(4)

Ссылки:

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.