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: