Monocle III: lente Optional

En la entrada anterior, Monocle II: lente Lens, realicé una descripción de la lente Lens, así como, la descripción de unos ejemplos de uso. En la presente entrada, Monocle III: lente Optional, me centraré en la lente Optional.

La lente Optional tiene un uso óptico para realizar un zoom en un producto; por ejemplo, una case class o un Map. La lente Optional tiene un uso óptico parecido a la lente Lens; pero, la diferencia, reside en que el elemento en el que se focaliza la operación puede no existir.

Optional tiene dos tipos de parámetros, llamados S y A: Optional[S, A], S representa el producto y A un elemento optinal de S. La lente está definida en el paquete monocle.Optional.

Para los ejemplos, utilizaremos una colección de enteros, representados en una lista, y una lente Optional para dicha colección. Así, definimos una lente Optional para la obtención de la cabeza de la lista de la siguiente manera:

val head = Optional[List[Int], Int] {
   // get
   case Nil => None
   case x :: xs => Some(x)
 } {
   // set
   a => {
     case Nil => Nil
     case x :: xs => a :: xs
   }
 }

La definición de la lente tiene la siguiente estructura: la primera parte, define la función get; y, la segunda, define la función set.

Operaciones básicas

Operación nonEmpty

Para determinar si una lista está vacía o no, se utiliza la función nonEmpty de la forma descrita en los siguientes ejemplos:

 println(s"1.- head.nonEmpty( List(1, 2, 3) )=${head.nonEmpty(xs)}")
 println(s"2.- head.nonEmpty( List.empty[Int] )=${head.nonEmpty(ys)}")

La salida por consola es la siguiente:

 1.- head.nonEmpty( List(1, 2, 3) )=true
 2.- head.nonEmpty( List.empty[Int] )=false

Operación Get

Para obtener el valor de la lente, se utiliza la función get de la forma descrita en los siguientes ejemplos:

 println(s"3.- head.getOrModify( List(1, 2, 3) )=${head.getOrModify(xs)}")
 println
 println(s"3.1.- head.getOrModify( List(1, 2, 3) ).getOrElse(0)=${head.getOrModify(xs).getOrElse(0)}")
 println
 println(s"4.- head.getOrModify( List.empty[Int] )=${head.getOrModify(ys)}")
 println
 println(s"4.1.- head.getOrModify( List.empty[Int] ).getOrElse(0)=${head.getOrModify(ys).getOrElse(0)}")
 println
 println(s"5.- head.getOption( List(1, 2, 3) )=${head.getOption(xs)}")
 println
 println(s"6.- head.getOption( List.empty[Int] )=${head.getOption(ys)}")
 println

La salida por consola es la siguiente:

 3.- head.getOrModify( List(1, 2, 3) )=\/-(1)
 3.1.- head.getOrModify( List(1, 2, 3) ).getOrElse(0)=1
 4.- {head.getOrModify( List.empty[Int] )=-\/(List())
 4.1.- head.getOrModify( List.empty[Int] ).getOrElse(0)=0
 5.- head.getOption( List(1, 2, 3) )=Some(1)
 6.- head.getOption( List.empty[Int] )=None

La función getOrModify es utiliza normalmente para polimorfísmo ópticos; y, getOption, es utilizada para monomorfirmos.

Operación Set

Para asignar un valor a la lente, se emplea la función set de la forma descrita en los siguiente ejemplos:

 println(s"7.- head.set(69)( List(1, 2, 3) )=${head.set(69)(xs)}")
 println
 println(s"8.- head.set(69)( List.empty[Int] )=${head.set(69)(ys)}")
 println
 println(s"13.- head.setOption(69)( List(1, 2, 3) )=${head.setOption(69)(xs)}")
 println
 println(s"14.- head.setOption(69)( List.empty[Int] )=${head.setOption(69)(ys)}")
 println

La salida por consola es la siguiente:

 7.- head.set(69)( List(1, 2, 3) )=List(69, 2, 3)
 8.- head.set(69)( List.empty[Int] )=List() 
 13.- head.setOption(69)( List(1, 2, 3) )=Some(List(69, 2, 3))
 14.- head.setOption(69)( List.empty[Int] )=None

Operación modificación

Para realizar una modificación de la lente, se emplea la función modify de la forma descrita en los siguiente ejemplos:

 println(s"9.- head.modify(_ + 1)( List(1, 2, 3) )=${head.modify(_ + 1)(xs)}") 
 println
 println(s"10.- head.modify(_ + 1)( List.empty[Int] )=${head.modify(_ + 1)(ys)}")
 println
 println(s"11.- head.modifyOption(_ + 1)( List(1, 2, 3) )=${head.modifyOption(_ + 1)(xs)}")
 println
 println(s"12.- head.modifyOption(_ + 1)( List.empty[Int] )=${head.modifyOption(_ + 1)(ys)}")
 println

La salida por consola es la siguiente:

 9.- head.modify(_ + 1)( List(1, 2, 3) )=List(2, 2, 3)
 10.- head.modify(_ + 1)( List.empty[Int] )=List()
 11.- head.modifyOption(_ + 1)( List(1, 2, 3) )=Some(List(2, 2, 3))
 12.- head.modifyOption(_ + 1)( List.empty[Int] )=None

En la siguiente entrada, Monocle IV: lente Prism, describiremos la lente Prism de la librería Monocle así como unos ejemplos prácticos.

Para el lector interesado, las entradas que he realizado sobre el tema son las siguientes:

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión /  Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión /  Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión /  Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión /  Cambiar )

Conectando a %s