How to perofrm a try and catch in ZIO?

Viewed 375

My first steps with ZIO, I am trying to convert this readfile function with a compatible ZIO version.

The below snippet compiles, but I am not closing the source in the ZIO version. How do I do that?

 def run(args: List[String]) =
    myAppLogic.exitCode

  val myAppLogic =
    for {
      _    <- readFileZio("C:\\path\\to\file.csv")
      _    <- putStrLn("Hello! What is your name?")
      name <- getStrLn
      _    <- putStrLn(s"Hello, ${name}, welcome to ZIO!")
    } yield ()

  def readfile(file: String): String = {
    val source = scala.io.Source.fromFile(file)
    try source.getLines.mkString finally source.close()
  }

  def readFileZio(file: String): zio.Task[String] = {
    val source = scala.io.Source.fromFile(file)
    ZIO.fromTry[String]{
      Try{source.getLines.mkString}
    }
    
  }
1 Answers

The simplest solution for your problem would be using bracket function, which in essence has similar purpose as try-finally block. It gets as first argument effect that closes resource (in your case Source) and as second effect that uses it.

So you could rewrite readFileZio like:

def readFileZio(file: String): Task[Iterator[String]] =
  ZIO(Source.fromFile(file))
    .bracket(
      s => URIO(s.close),
      s => ZIO(s.getLines())
  )

Another option is to use ZManaged which is a data type that encapsulates the operation of opening and closing resource:

def managedSource(file: String): ZManaged[Any, Throwable, BufferedSource] = 
   Managed.make(ZIO(Source.fromFile(file)))(s => URIO(s.close))

And then you could use it like this:

def readFileZioManaged(file: String): Task[Iterator[String]] =
    managedSource(file).use(s => ZIO(s.getLines()))
Related