Emparejamiento de Patrones
## Objetivos de Aprendizaje
- Dominar expresiones match
- Aprender tipos de patrones
- Usar guardas en patrones
- Trabajar con case objects
- Comprender extractors
## Expresion match Basica
### Sintaxis
```scala
val x = 10
val result = x match {
case 1 => "one"
case 2 => "two"
case 3 => "three"
case _ => "something else"
}
```
### match como Expresion
```scala
def describe(x: Any): String = x match {
case 1 => "one"
case "hello" => "a greeting"
case true => "truth"
case List(1, 2, 3) => "list of three numbers"
case _ => "unknown"
}
```
## Tipos de Patrones
### Patrones Constante
```scala
def describe(x: Any): String = x match {
case 0 => "zero"
case true => "true"
case "hello" => "greeting"
case '\n' => "newline"
case _ => "other"
}
```
### Patrones Variable
```scala
def describe(x: Any): String = x match {
case 0 => "zero"
case something => s"value is $something"
}
```
### Patron Wildcard
```scala
x match {
case 1 => "one"
case _ => "not one"
}
```
### Patrones de Tipo
```scala
def describe(x: Any): String = x match {
case i: Int => s"Integer: $i"
case s: String => s"String: $s"
case l: List[_] => s"List with ${l.length} elements"
case _: BigInt => "big integer"
case null => "null"
case _ => "something else"
}
```
### Patrones de Lista
```scala
def describeList(lst: List[Int]): String = lst match {
case List() => "empty list"
case List(x) => s"single element: $x"
case List(x, y) => s"two elements: $x and $y"
case List(x, _*) => s"first element: $x, and more"
case _ => "not a list"
}
// Patrones Cons
def sum(lst: List[Int]): Int = lst match {
case head :: tail => head + sum(tail)
case Nil => 0
}
```
### Patrones de Tupla
```scala
def describeTuple(t: (Any, Any)): String = t match {
case (x: Int, y: Int) => s"int pair: ($x, $y)"
case (x: String, _) => s"string first: $x"
case (_, _) => "any 2-tuple"
}
// Destructuring en patrones
def add(tuple: (Int, Int, Int)) = tuple match {
case (a, b, c) => a + b + c
}
```
### Patrones de Case Class
```scala
case class Person(name: String, age: Int)
def describe(p: Person): String = p match {
case Person("Alice", 30) => "Alice is 30"
case Person(name, age) => s"$name is $age years old"
}
val alice = Person("Alice", 30)
alice match {
case Person(n, a) => println(s"$n, $a")
}
```
### Patrones de Clase Sellada
```scala
sealed trait Result
case class Success(data: Int) extends Result
case class Failure(message: String) extends Result
case object Pending extends Result
def describe(result: Result): String = result match {
case Success(n) => s"Success with $n"
case Failure(msg) => s"Failed: $msg"
case Pending => "Still pending"
}
```
## Guardas
### Agregando Condiciones
```scala
def describe(x: Int): String = x match {
case i if i > 0 => "positive"
case i if i < 0 => "negative"
case 0 => "zero"
}
def grade(score: Int): Char = score match {
case s if s >= 90 => 'A'
case s if s >= 80 => 'B'
case s if s >= 70 => 'C'
case s if s >= 60 => 'D'
case _ => 'F'
}
```
### Combinando Patrones y Guardas
```scala
def describeList(lst: List[Int]): String = lst match {
case List(1, _*) if lst.length >= 3 => "starts with 1, has 3+ elements"
case List(x, y, z) if x + y == z => s"$x + $y = $z"
case _ => "other"
}
```
## Case Objects
```scala
sealed trait Status
case object Ready extends Status
case object Running extends Status
case object Done extends Status
case object Failed extends Status
def describe(status: Status): String = status match {
case Ready => "Ready to start"
case Running => "Currently running"
case Done => "Completed successfully"
case Failed => "Failed"
}
```
## Extractors
### Metodo unapply
```scala
class Person(val name: String, val age: Int)
object Person {
def apply(name: String, age: Int): Person = new Person(name, age)
def unapply(p: Person): Option[(String, Int)] = Some((p.name, p.age))
}
val p = Person("Alice", 30)
p match {
case Person(name, age) => s"$name is $age"
}
// Tambien puede funcionar con tupla regular
val tuple = ("Bob", 25)
tuple match {
case (name, age) => s"$name is $age"
}
```
### Extractors Booleanos
```scala
object Even {
def unapply(n: Int): Boolean = n % 2 == 0
}
42 match {
case Even() => "even"
case _ => "odd"
}
```
### Extractors Personalizados
```scala
object Email {
def unapply(str: String): Option[(String, String)] = {
val parts = str.split("@")
if (parts.length == 2) Some(parts(0), parts(1))
else None
}
}
"user@example.com" match {
case Email(user, domain) => s"User: $user, Domain: $domain"
case _ => "Not an email"
}
```
## Emparejamiento de Patrones en Asignaciones
```scala
val (x, y) = (1, 2)
val List(first, second, _*) = List(1, 2, 3, 4, 5)
val Person(n, a) = Person("Alice", 30)
```
## Emparejamiento de Patrones en Bucles for
```scala
val people = List(("Alice", 30), ("Bob", 25), ("Charlie", 35))
for ((name, age) <- people if age >= 30) {
println(s"$name is $age")
}
// Con emparejamiento de patrones
people foreach {
case (name, age) if age >= 30 => println(s"$name is $age")
case (name, _) => println(s"$name is too young")
}
```
## Patrones Regex
```scala
val emailRegex = "([a-z]+)@([a-z]+)\\.([a-z]+)".r
"user@example.com" match {
case emailRegex(user, domain, tld) =>
s"User: $user, Domain: $domain, TLD: $tld"
case _ => "Invalid email"
}
// Extraccion
val emailRegex(user, domain, tld) = "user@example.com"
// user = "user", domain = "example", tld = "com"
```
## Funciones Parciales
```scala
val divide: PartialFunction[(Int, Int), Int] = {
case (a, b) if b != 0 => a / b
}
divide.isDefinedAt((10, 2)) // true
divide.isDefinedAt((10, 0)) // false
divide((10, 2)) // 5
```
## Patrones Exhaustivos
El compilador de Scala advierte sobre coincidencias no exhaustivas con tipos sellados:
```scala
sealed trait Color
case object Red extends Color
case object Green extends Color
case object Blue extends Color
def describe(color: Color): String = color match {
case Red => "red"
case Green => "green"
// Advertencia del compilador: falta Blue
}
```
## Resumen
- `match` es la expresion potente de emparejamiento de patrones de Scala
- Los patrones incluyen constantes, variables, tipos, listas, tuplas y case classes
- Las guardas (`if`) agregan condiciones a los patrones
- Los case objects representan valores singleton en jerarquias selladas
- Los extractors (`unapply`) permiten emparejamiento de patrones personalizado
- Los tipos sellados permiten coincidencia exhaustiva
- Las funciones parciales manejan escenarios de subconjunto de casos
- El emparejamiento de patrones funciona en asignaciones y comprehensions
Comments
Comments powered by Giscus
To enable comments, add your Giscus embed code here.
Learn more about Giscus →