← Scala EspañolChapter 09 of 13

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 →