Exit e-book
Show all chapters
05
Special support for ZRef
05. 
Special support for ZRef
Improve your focus with ZIO optics
05

Special support for ZRef

ZIO Optics provides special support for ZRef, by adding some extension methods to it which use optics under the hood. There are several extension methods according to the contents inside the ZRef. For example, if it contains a Chunk:

val chunk: Ref[Chunk[Int]] = ???

chunk.at(10) // Access the specified index of `chunk`
chunk.filter(_ % 2 == 0) // Filter elements of a `chunk`
chunk.slice(2, 5) // Access a slice of `chunk`

If it contains a List:

val list: Ref[List[Int]] = ???

list.cons // Access the `::` case of `list`
list.head // Access the head of `list`
list.tail // Access the tail of `list`

If it contains a Tuple2:

val tuple: Ref[(Int, String)] = ???

tuple.first  // Access the first element of `tuple`
tuple.second // Access the second element of `tuple`

If it contains a Map:

val map: Ref[Map[String, Int]] = ???

map.key("someKey") // Access the given key of `map`

If it contains an Either:

val either: Ref[Either[String, Int]] = ???

either.left  // Access the Left case of `either`
either.right // Access the Right case of `either`

And, it contains an Option:

val option: Ref[Option[Int]] = ???

option.none // Access the None case of `option`
option.some // Access the Some case of `option`

Let’s see a concrete example of how useful this is. Let’s say we have a Ref containing a Map whose keys are movie titles and whose values are movie descriptions:

type Title       = String
type Description = String

val movieDescriptionsByTitleRef: Ref[Map[Title, Description]] = ???

We want to write a method to update the description of the given movie. Without ZIO Optics, it would look like this:

def updateMovieDescription(title: Title, newDescription: Description): Task[Unit] =
  movieDescriptionsByTitleRef.modify { movieDescriptionsByTitle =>
    movieDescriptionsByTitle.get(title) match {
      case Some(_) =>
        (ZIO.unit, movieDescriptionsByTitle + (title -> newDescription))
      case None =>
        (
          ZIO.fail(new NoSuchElementException(s"Movie with title $title not found")),
          movieDescriptionsByTitle
        )
    }
  }.flatten

But with ZIO Optics, we have a cleaner and more declarative implementation:

import zio.optics._

def updateMovieDescription2(title: String, newDescription: String): Task[Unit] =
  movieDescriptionsByTitleRef.key(title).update(_ => newDescription)

 

PREVIOUS
Chapter
04
NEXT
Chapter
06