Last active
April 5, 2016 13:03
-
-
Save rbonvall/d11b21a259ff498c2f88041904f15507 to your computer and use it in GitHub Desktop.
Charla «Unos tipos con opciones».
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Unos tipos con opciones // | |
// // | |
// Roberto Bonvallet // | |
// @rbonvall // | |
// // | |
// Viernes 1 de abril de 2016 // | |
// Santiago Scala Meetup // |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// El tipo de retorno de esta función | |
// no dice todo lo que la función podría hacer: | |
def f(x: Double): Double = { | |
println(x) | |
throw new Exception("...") | |
Request("http://deep.web/córneas") | |
null | |
} | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Existen tipos que sí describen | |
// los distintos efectos que puede tener un valor: | |
def f(x: Double): Option[Double] // podría no existir; | |
def f(x: Double): List[Double] // podría ser más de uno; | |
def f(x: Double): Try[Double] // podría fallar; | |
def f(x: Double): Try[Option[Double]] // podría fallar o no existir; | |
def f(x: Double): Future[Double] // podría demorarse y fallar; | |
def f(x: Double): Observable[Double] // permite suscribirse; | |
def f(x: Double): IO[Double] // interactúa con el mundo externo (en lenguajes como Haskell). |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// El tipo Option[T] representa un valor que podría o no existir. | |
// Obliga al programador a considerar ambos casos explícitamente. | |
def f(x: Double): Option[Double] | |
val y = f(9.99) match { | |
case Some(value) ⇒ 3.14 * value | |
case None ⇒ 1.23 | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Por ejemplo, el metodo .find de las listas retorna un Option: | |
val xs = List(17, 24, 33, 1, 19, 24) | |
xs.find(_ % 3 == 0) // → Some(24) | |
xs.find(_ % 7 == 0) // → None | |
// Un método conveniente de los Option es .getOrElse, | |
// que permite obtener un valor con seguridad: | |
xs.find(_ % 3 == 0).getOrElse(10) // → 24 | |
xs.find(_ % 7 == 0).getOrElse(10) // → 10 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Ejemplo: encontrar una fecha para hacer una fiesta | |
val partyDay: Date = | |
myFriends.find { f ⇒ f.birthday.month == 4 } // Buscar algún amigo que tenga cumpleaños en abril. | |
.map { f ⇒ f.birthday.copy(year=2016) } // Si lo hay, tomar su fecha de nacimiento y cambiarla a este año | |
.getOrElse(Date(2016, 4, 30)) // y si no lo hay, retornar el 30 de abril de este año. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// .fold es un método más type-safe de hacer .map+.getOrElse | |
val partyDay: Date = | |
myFriends.find { f ⇒ f.birthday.month == 4 } | |
.fold ((Date(2016, 4, 30))) { f ⇒ f.birthday.copy(year=2016) } |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Creemos una clase Cardinality, que representa cuántas veces un elemento puede existir. | |
// Siempre hay un límite inferior (por lo menos cero veces), | |
// pero podría no haber un límite superior (algo podría aparecer un número ilimitado de veces). | |
case class Cardinality(min: Int, max: Option[Int]) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Algunos requerimientos son: | |
// el mínimo no puede ser negativo, | |
// el máximo (si existe) no puede ser menor que 1, | |
// el máximo (si existe) no puede ser menor que el mínimo. | |
case class Cardinality(min: Int, max: Option[Int]) { | |
require(min >= 0) | |
max match { | |
case Some(m) ⇒ | |
require(m >= 1) | |
require(m >= min) | |
case None ⇒ | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Usando métodos del tipo Option podemos reescribir el pattern match más claramente. | |
// Aunque en este caso es seguro (pues verificamos antes si es vacío), | |
// siempre es mejor evitar usar max.get. | |
case class Cardinality(min: Int, max: Option[Int]) { | |
require(min >= 0) | |
require(max.isEmpty || max.get >= 0) | |
require(max.isEmpty || max.get >= min) | |
} | |
// max.isEmpty es lo mismo que !max.isDefined |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// El método .forall permite reescribir la condición anterior | |
// de manera completamente segura: | |
case class Cardinality(min: Int, max: Option[Int]) { | |
require(min >= 0) | |
require(max.forall(_ >= 1)) | |
require(max.forall(_ >= min)) | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Agreguemos una representación glamorosa en string para nuestra clase: | |
case class Cardinality(min: Int, max: Option[Int]) { | |
require(min >= 0) | |
require(max.forall(_ >= 1)) | |
require(max.forall(_ >= min)) | |
override def toString = max match { | |
case Some(m) if m == min ⇒ s"Cardinality($min)" | |
case Some(m) ⇒ s"Cardinality($min, $m)" | |
case None ⇒ s"Cardinality($min, ∞)" | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Nuevamente, podemos reescribir el pattern match usando métodos de Option: | |
case class Cardinality(min: Int, max: Option[Int]) { | |
require(min >= 0) | |
require(max.forall(_ >= 1)) | |
require(max.forall(_ >= min)) | |
override def toString = | |
if (max.contains(min)) s"Cardinality($min)" | |
else s"Cardinality($min, ${max.getOrElse("∞")})" | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Ejemplos de uso de nuestra clase: | |
println(Cardinality(3, Some(3))) // → Cardinality(3) | |
println(Cardinality(3, Some(5))) // → Cardinality(3, 5) | |
println(Cardinality(3, None)) // → Cardinality(3, ∞) | |
println(Cardinality(3, Some(2))) // → IllegalArgumentException | |
println(Cardinality(-1, None)) // → IllegalArgumentException | |
println(Cardinality(0, Some(0))) // → IllegalArgumentException |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment