Comprender las opciones en Scala

Suraj P 12 julio 2022
  1. el tipo Option en Scala
  2. Recuperar el Valor de la Option en Scala
  3. la Option como Contenedor en Scala
Comprender las opciones en Scala

En este artículo, aprenderemos cómo trabajar con elementos de datos opcionales en Scala. Las Option en Scala nos ayudan a escribir código robusto.

el tipo Option en Scala

Option[T] en un Scala es un contenedor que almacena cero o un valor de un tipo dado. Manejando valores opcionales usando la Option de Scala, podemos asegurar dos cosas:

  1. Tipo seguridad: Podemos parametrizar los valores opcionales.
  2. Conciencia funcional: el tipo Option proporciona muchas capacidades funcionales que aseguran que se creen menos errores en el programa.

En Scala, una Option[T] está representada por el objeto Some[T] o None[T]. Aquí scala.Option es la clase base que es abstracta y extendida, haciendo que la Option en Scala se comporte como un contenedor.

Recuerda que la clase Option y sus subclases requieren un tipo concreto. Pueden ser explícitos o inferidos como la siguiente sintaxis.

Ejemplo:

val obj1: Option[Int] = None
val obj2 = Some(100)

Aquí obj1 y obj2 son objetos de Option[Int]. Una pregunta común es cómo comprobar si nuestra Option es Some o None.

Para resolver este problema, tenemos las siguientes funciones.

  1. isEmpty: este método devuelve true si el objeto es None.
  2. nonEmpty: este método devuelve true si el objeto es Some.
  3. isDefined: este método devuelve true si el objeto es Some.

Recuperar el Valor de la Option en Scala

Podemos usar el método get para recuperar el valor de Option. Si se invoca el método get en un objeto de None, entonces se lanza NoSuchElementException, también conocido como sesgo de éxito.

Código de ejemplo:

val obj1: Option[Int]= ...

val v1 = if (obj1.isDefined)
{
  obj1.get
}
else
{
  0
}

El código anterior también se puede escribir utilizando la coincidencia de patrones.

Código de ejemplo:

val obj1: Option[Int]= ...

val v1 = obj1 match {
  case Some(temp) =>
    temp
  case None =>
    0
}

También tenemos otros métodos como getOrElse y orElse para recuperar valores.

  1. getOrElse: Este método recupera valores si el objeto es Some; de lo contrario, devuelve un valor predeterminado.
  2. orElse: Este método recupera valores si el objeto es Some; de lo contrario, devuelve una opción alternate.

Cuando el valor opcional no está establecido, el método getOrElse es muy útil ya que podemos devolver un valor predeterminado.

Sintaxis:

val v1 = obj1.getOrElse(0)

la Option como Contenedor en Scala

Como hemos visto que Option es un contenedor en Scala para otro valor, así como atravesamos una List de manera similar, podemos atravesar una Option.

Veamos algunos métodos para este contenedor. Sintaxis del método Option.map en Scala:

final def map[Y](f: (X) => Y): Option[Y]

Código de ejemplo:

val obj1: Option[Int] = Some(100)
assert(obj1.map(_.toString).contains("100"))
assert(obj1.map(_ * 2.0).contains(200))

val obj2: Option[Int] = None
assert(obj2.map(_.toString).isEmpty)

En el ejemplo anterior, usamos el método Option.map para convertir los valores contenidos a otro tipo. El método Option.map también podría usarse para afectar el control de flujo del programa.

Código de ejemplo:

val obj1: Option[Int] = Some(10)
val obj2: Option[Int] = None

def mul(n: Int): Int = n * 2

assert(obj1.map(mul).contains(20))
assert(obj2.map(mul).isEmpty)

Aquí creamos dos objetos de Opción[Int], el primer objeto tiene un valor de 10, y el segundo está vacío. Luego definimos un método mul que multiplica la entrada por 2.

Finalmente, mapeamos obj1 y obj2 utilizando el método mul. Mapear obj1 nos da Some(20), y mapear obj2 nos da None.

Una cosa a observar aquí es que en la segunda llamada, obj2.map(mul), el método mul no se llama en absoluto. También podemos controlar el flujo con filtrado.

Tenemos muchos métodos para hacerlo:

  1. filtro: este método devuelve Option si el valor de Option es Some y la función proporcionada devuelve true.
  2. existe: este método devuelve true si la Option está configurada y la función suministrada devuelve true.
  3. forall: Se comporta igual que el método exists.

Usando estas funciones, podemos escribir el código de manera muy concisa.

Pongamos un ejemplo en el que encontremos el equipo con la puntuación más alta.

Código de ejemplo:

 def highScoringTeam(playerA: Player, playerB: Player, tournament: Tournament): Option[(Player, Int)] =
 { getTopScore(playerA, tournament).foldRight(getTopScore(playerB, tournament)) {
      case (playerAInfo, playerBInfo) => playerBInfo.filter {
        case (_, scoreB) => scoreB > playerAInfo._2
      }.orElse(Some(playerAInfo))
    }
  }

En el código anterior, hemos aprovechado que las Option se pueden usar como colecciones. La única diferencia es que una opción puede tener como máximo un valor.

Autor: Suraj P
Suraj P avatar Suraj P avatar

A technophile and a Big Data developer by passion. Loves developing advance C++ and Java applications in free time works as SME at Chegg where I help students with there doubts and assignments in the field of Computer Science.

LinkedIn GitHub