From 5a018475687f18115f8e3b1ed33f864ce0399a92 Mon Sep 17 00:00:00 2001 From: Bruce Eckel Date: Mon, 22 Jul 2024 16:46:35 -0600 Subject: [PATCH] "Failure" might be complete #bruce #time 15m --- Chapters/06_Failure.md | 38 +++++------------------ graveyard/06_Short_Circuiting_Failures.md | 22 +++++++++++++ 2 files changed, 30 insertions(+), 30 deletions(-) create mode 100644 graveyard/06_Short_Circuiting_Failures.md diff --git a/Chapters/06_Failure.md b/Chapters/06_Failure.md index 523c1630..177a9d15 100644 --- a/Chapters/06_Failure.md +++ b/Chapters/06_Failure.md @@ -503,33 +503,10 @@ def run = We don't see the `ClimateFailure` error, we only get its `message` as produced by the `catchAll`. -## Short-circuiting Failures - -Despite the downsides of throwing `Exception`s, there is a reason it is a common practice. -It is a quick and easy way to stop the function when something goes wrong, without wrapping your logic in `if/else`. - -With Effects, we achieve the same behavior without the downsides. - -This triggers a `gpsFailure`, causing the *first* Effect to fail: - -```scala 3 mdoc:runzio -import zio.* - -override val bootstrap = gpsFailure - -def run = - weatherReport -``` - -The program fails with the GPS failure, and the `check` Effect does not run. - -Short-circuiting is an essential part of user-friendly Effect Systems. -With it, we can write a linear sequence of fallible expressions, while tracking all possible failures. - ## Handling Thrown Exceptions -So far our example Effects have **returned** `Exception`s to indicate failure, but you may have legacy code or external libraries which **throw** `Exception`s instead. -In these situations there are ways to wrap the `Exception`-throwing code so that we achieve our preferred style of returning `Exception`s. +So far our example Effects have _returned_ `Exception`s to indicate failure, but you may have legacy code or external libraries that _throw_ `Exception`s instead. +In these situations you can wrap the `Exception`-throwing code to achieve our preferred style of returning `Exception`s. ```scala 3 mdoc:invisible import zio.* @@ -547,7 +524,7 @@ def getTemperatureOrThrow: String = ``` The `getTemperatureOrThrow` function can fail by throwing an `Exception`. -If we call this function from an Effect, a failure causes the program to fail: +If we call this function from an Effect, the program fails: ```scala 3 mdoc:runzio import zio.* @@ -561,7 +538,7 @@ def run = Despite our claim that this Effect `succeed`s, it crashes with a defect. When we call side-effecting code, the Effect System can't warn us about the potential failure. -The solution is to use `ZIO.attempt`, which captures thrown `Exception`s as the error type of the Effect: +The solution is to use `ZIO.attempt`, which turns thrown `Exception`s into Effects: ```scala 3 mdoc:silent import zio.* @@ -571,7 +548,8 @@ val safeTemperatureApp = getTemperatureOrThrow ``` -Now you can use any of the failure handling mechanisms in Effects to deal with the failure: +Now you can use an Effect failure-handling mechanism. +Here we use `orElse`: ```scala 3 mdoc:runzio import zio.* @@ -584,7 +562,7 @@ def run = "Could not get temperature" ``` -Here we handle the Effect's failure with a fallback Effect, which succeeds. +The Effect's failure is handled with a fallback, which succeeds. Thrown `Exception`s are inherently unpredictable, so it is preferable to encapsulate all exception-throwing functions into Effects. -This makes that unpredictability clear and provides mechanisms for handling possible failures. +This makes the unpredictability clear and provides better mechanisms for handling failures. diff --git a/graveyard/06_Short_Circuiting_Failures.md b/graveyard/06_Short_Circuiting_Failures.md new file mode 100644 index 00000000..cea4a6ed --- /dev/null +++ b/graveyard/06_Short_Circuiting_Failures.md @@ -0,0 +1,22 @@ +## Short-circuiting Failures + +Despite the downsides of throwing `Exception`s, there is a reason it is a common practice. +It is a quick and easy way to stop the function when something goes wrong, without wrapping your logic in `if/else`. + +With Effects, we achieve the same behavior without the downsides. + +This triggers a `gpsFailure`, causing the *first* Effect to fail: + +```scala 3 mdoc:runzio +import zio.* + +override val bootstrap = gpsFailure + +def run = + weatherReport +``` + +The program fails with the GPS failure, and the `check` Effect does not run. + +Short-circuiting is an essential part of user-friendly Effect Systems. +With it, we can write a linear sequence of fallible expressions, while tracking all possible failures. \ No newline at end of file