Strange behavior of ZIO's map method or yield in for comprehension

165 Views Asked by At

I faced that ZIO.map invokes private ZIO.succeedNow which seems will fail running fiber without any chance of handle error
Here is an example:

  private val program: ZIO[Any, Throwable, Int] = for {
    _ <- ZIO.succeed(println("Start"))
  } yield 1 / 0

  override def run: ZIO[Any, Any, Unit] = program
    .catchAll(e => ZIO.succeed(println(e.getMessage))) *>
    ZIO.succeed(println("DONE"))

The output will never print "DONE" in console
The same behavior observed when I'll change the val program to:

  private val program: ZIO[Any, Throwable, Int] = for {
    _ <- ZIO.succeed(println("Start"))
    r <- ZIO.succeed(1 / 0)
  } yield r

But when I'm excluding invocation of succeed() everything works fine and I'm getting "DONE" in console
This snippet bellow works as expected

  private val program: ZIO[Any, Throwable, Int] = for {
    _ <- ZIO.succeed(println("Start"))
    r <- ZIO.from(1 / 0)
  } yield r

And finally catchAll is invoked
The question is why ZIO.map suppose that passed function should not be failed, and why if it fails I have no chance to handle this error?

1

There are 1 best solutions below

4
Gaël J On

In your first example, as you said, you're using ZIO#map() which semantic/contract is to be used with a function that do not raise exceptions.

If you break this intended usage, you get a defect (read more about it) which as you noticed is not caught by catchAll but would be using catchAllDefect (read more about it).

In your second example, the result is the same because this time you break the intended usage of ZIO.succeed() by giving it a non successful value.