ZIO 2 example: ZIO.fail, ZIO.succeed, ZIO.attempt, orElseFail, and orDie

As a “note to self” about using ZIO 2, here are a few ZIO examples that show the ZIO.fail, ZIO.succeed, ZIO.attempt, orElseFail, and orDie methods and functions.

Before looking at the following code, it’s important to know that it uses the following Scala 3 enum:

enum FailureReason:
     case NoCommandLineArgs, InvalidNumberOfArgs, InvalidIntForMinutes, InvalidIntForGain,
          CouldNotCreateAudioStream, CouldNotCreateClip, CouldNotPlayClip

First, here’s an example of using ZIO.fail and ZIO.succeed:

def checkForZeroArgs(args: Chunk[String]): ZIO[Any, FailureReason, Unit] = 
    if args.size == 0 then ZIO.fail(NoCommandLineArgs) else ZIO.succeed(())

Here is ZIO.attempt and orElseFail:

def getMinutesToWait(args: Chunk[String]): ZIO[Any, FailureReason, Int] = 
    ZIO.attempt(args(0).toInt)
       .orElseFail(InvalidIntForMinutes)

This function shows ZIO.attempt, orElseFail, and ZIO.succeed:

def getGainControl(args: Chunk[String]): ZIO[Any, FailureReason, Int] = 
    if args.size == 2 then
        ZIO.attempt(args(1).toInt)
           .orElseFail(InvalidIntForGain)
    else
        ZIO.succeed(DefaultGain)

ZIO’s orDie function

And last, this function shows how to use orDie:

def countdownEffect(minutesToWait: Int): ZIO[Any, Nothing, Unit] = 
    ZIO.foreachDiscard(1 to minutesToWait) { minute =>
        ZIO.sleep(1.second) *>
            printLine(s"time remaining: ${minutesToWait - minute} ...").orDie
    }

Note that the error type in that function is Nothing. This is the way orDie works:

  1. It takes a ZIO effect that can fail with some error type.
  2. It returns a new ZIO effect that can’t fail — has Nothing as its error type.
  3. If the original effect succeeds, orDie passes through the success value.
  4. If the original effect fails, orDie converts the failure into a defect, which typically results in the program crashing.

So basically a ZIO FAILURE is an exception you expect and want to handle (like handling an IOException), while a DEFECT is something you can’t control (like being unable to print to STDOUT, running out of memory, etc.). A defect will generally cause your application to crash/terminate.

In summary, if you’re interested in functional error handling with ZIO 2, I hope these examples are helpful.