Найти в Дзене

Pattern matching в Scala - приятное с полезным

Pattern matching - очень мощный инструмент, благодаря которому мы можем добиться высокой гибкости и краткости кода, но при его использовании стоит помнить пару ньюансов. Каких? Сейчас расскажу! Если сказать в двух словах, что такое pattern matching, - это switch-case на стероидах, способный работать с множеством различных типов и параметров, например: def patt(a: Any) = a match {
case _:String => println("String")
case n:Number => println(n)
case _ => println("Smth else")
}
patt(2)
patt("Valera")
patt(new Object) Используя ключевое слово match мы применяем матчинг внутри функции patt на входящий параметр "а", как можно заметить, "а:Any", а это значит, что в качестве аргумента может быть любой обьект(см. иерархия типов Scala), и далее мы говорим "case _:String", что означает "если параметр - стринга - то делай =>это". Выглядит довольно просто, не так ли? Последней строкой "case _ =>" мы даём знать, что "если нет подходящего из каких-либо прошлых кейсов, то в крайнем случае делай

Pattern matching - очень мощный инструмент, благодаря которому мы можем добиться высокой гибкости и краткости кода, но при его использовании стоит помнить пару ньюансов. Каких? Сейчас расскажу!

Если сказать в двух словах, что такое pattern matching, - это switch-case на стероидах, способный работать с множеством различных типов и параметров, например:

def patt(a: Any) = a match {
case _:String =>
println("String")
case n:Number =>
println(n)
case _ =>
println("Smth else")
}

patt(2)
patt("Valera")
patt(new Object)

Используя ключевое слово match мы применяем матчинг внутри функции patt на входящий параметр "а", как можно заметить, "а:Any", а это значит, что в качестве аргумента может быть любой обьект(см. иерархия типов Scala), и далее мы говорим "case _:String", что означает "если параметр - стринга - то делай =>это". Выглядит довольно просто, не так ли? Последней строкой "case _ =>" мы даём знать, что "если нет подходящего из каких-либо прошлых кейсов, то в крайнем случае делай это", эдакий предохранитель.

В матчинге очень удобно использовать case class'ы, что, собственно, и используется. Сигнатура создания такого класса проста:

case class User(name: String, age: Int)

И далее мы можем использовать его для нашего матча, добавляя guardians(if-statement внутри match):

def patt(user: User) = user match{

case User(name, age) if age >= 18 => "продаём алко"

case User(name, age) if age <= 0 => "ошибка, как так лет меньше нуля?!"

case User(name, age) => s"$name, тебе ещё нельзя!"

}

Матчить таким образом можно почти что угодно, за исключением generic - т.е. List[String] и List[Int] он не различит, ошибки не будет, но матч зайдёт в 1й в списке лист.

Спросите вы, можно ли матчить обычные классы, а не кейс? Можно, но для этого необходимо провернуть небольшой трик - создать объект-компаньон для необходимого класса и обозначть там метод unapply(), но к такому решению стоит прибегать лишь в крайних случаях, лучше используйте кейс-классы.

Если Вам интересны эти темы, дайте знать, и я постараюсь описать вопрос глубже, данная же статья скорее ознакомительная.