8000 docs: Clean up some grammar & syntax in core reference by ches · Pull Request #8276 · zio/zio · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

docs: Clean up some grammar & syntax in core reference #8276

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jul 28, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 14 additions & 14 deletions docs/reference/control-flow/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@ title: "Introduction to ZIO's Control Flow Operators"
sidebar_label: "Control Flow"
---

Although we have access to built-in scala control flow structures, ZIO has several control flow combinators. In this section, we are going to introduce different ways of controlling flows in ZIO applications.
Although we have access to built-in Scala control flow structures, ZIO has several control flow combinators. In this section, we are going to introduce different ways of controlling flows in ZIO applications.

## `if` Expression

When working with ZIO values, we can also work with built-in scala if-then-else expressions:
When working with ZIO values, we can use built-in Scala if-then-else expressions:

```scala mdoc:compile-only
import zio._
Expand Down Expand Up @@ -124,7 +124,7 @@ def flipTheCoin: ZIO[Any, IOException, Unit] =

## Loop Operators

In imperative scala code base, sometime we may use `while(condition) { statement }` or `do { statement } while (condition)` structs to perform loops:
In imperative Scala code bases, sometimes we may use `while(condition) { statement }` or `do { statement } while (condition)` constructs to perform loops:

```scala mdoc:compile-only
object MainApp extends scala.App {
Expand All @@ -143,7 +143,7 @@ object MainApp extends scala.App {
// 3
```

But in functional scala, we tend to not use mutable variable. So to have a loop, we would like to use recursions. Let's rewrite the previous example, using recursion:
But in functional Scala, we tend to avoid mutable variables. So to have a loop, we would like to use recursion. Let's rewrite the previous example using recursion:

```scala mdoc:compile-only
import scala.annotation.tailrec
Expand Down Expand Up @@ -198,11 +198,11 @@ object MainApp extends ZIOAppDefault {
}
```

After this very short introduction to writing loops in functional scala, now let us go deep into ZIO specific combinators for writing loops:
After this short introduction to writing loops in functional Scala, now let us go further into ZIO-specific combinators for writing loops:

### `loop`

The `ZIO.loop` operator takes an initial state, then repeatedly change the state based on the given `inc` function, until the given `cont` function is evaluated to true:
The `ZIO.loop` operator takes an initial state, then repeatedly changes the state based on the given `inc` function, until the given `cont` function evaluates to true:

```scala
object ZIO {
Expand All @@ -215,9 +215,9 @@ object ZIO {
)(cont: S => Boolean, inc: S => S)(body: S => ZIO[R, E, Any]): ZIO[R, E, Unit]
```

The `ZIO#loop` collects all intermediate states in a list and returns it finally, while the `ZIO.loopDiscard` discards all results.
`ZIO.loop` collects all intermediate states in a list and returns it finally, while the `ZIO.loopDiscard` discards all results.

We can think of `ZIO#loop` as a moral equivalent of the following while loop:
We can think of `ZIO.loop` as a moral equivalent of the following while loop:

```scala
var s = initial
Expand Down Expand Up @@ -372,7 +372,7 @@ def getNames: ZIO[Any, IOException, List[String]] =

### `foreach`

Note that, in several cases, we can avoid these low-level operators and instead use the high-level ones. For example, let's try to rewrite the `r5` with `ZIO.foreach`:
Note that, in several cases, we can avoid these low-level operators and instead use high-level ones. For example, let's try to rewrite the `r5` with `ZIO.foreach`:

```scala mdoc:compile-only
import zio._
Expand All @@ -390,21 +390,21 @@ Console.printLine("Please enter three names:") *>

## try/catch/finally

When working with resources, just like the scala's `try`/`catch`/`finally` construct, in ZIO we have a similar operator called `acquireRelease` and also `ensuring`. We discussed them in more detail in the [resource management section](../resource/index.md). But, for now, we want to focus on their control flow behaviors.
When working with resources, just like Scala's `try`/`catch`/`finally` construct, in ZIO we have a similar operator called `acquireRelease` and also `ensuring`. We discussed them in more detail in the [resource management section](../resource/index.md). But, for now, we want to focus on their control flow behaviors.

Let's learn about the `ZIO.acquireReleaseWith` operator. This operator takes three effects:

1. **`acquire`** an effect that describes the resource acquisition
2. **`release`** an effect that describes the release of the resource
3. **`use`** an effect that describes resource usage
1. **`acquire`**, an effect that describes the resource acquisition
2. **`release`**, an effect that describes the release of the resource
3. **`use`**, an effect that describes resource usage

```scala mdoc:compile-only
import zio._

ZIO.acquireReleaseWith(acquire = ???)(release = ???)(use = ???)
```

This operator guarantees us that if the _resource acquisition (acquire)_ the _release_ effect will be executed whether the _use_ effect succeeded or not:
This operator guarantees us that if the _resource acquisition (acquire)_ succeeds, the _release_ effect will be executed whether the _use_ effect succeeded or not:

```scala mdoc:compile-only
import java.io.IOException
Expand Down
34 changes: 17 additions & 17 deletions docs/reference/core/cause.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,17 @@ id: cause
title: "Cause"
---

The `ZIO[R, E, A]` effect is polymorphic in values of type `E` and we can work with any error type that we want, but there is a lot of information that is not inside an arbitrary `E` value. So as a result ZIO needs somewhere to store things like **unexpected error or defects**, **stack and execution traces**, **cause of fiber interruptions**, and so forth.
The `ZIO[R, E, A]` effect is polymorphic in values of type `E` and we can work with any error type that we want, but there is a lot of information that is not inside an arbitrary `E` value. So as a result ZIO needs somewhere to store things like **unexpected errors or defects**, **stack and execution traces**, **cause of fiber interruptions**, and so forth.

ZIO is very strict about preserving the full information related to a failure. It captures all type of errors into the `Cause` data type. ZIO uses the `Cause[E]` data type to store the full story of failure. So its error model is **lossless**. It doesn't throw information related to the failure result. So we can figure out exactly what happened during the operation of our effects.
ZIO is very strict about preserving the full information related to a failure. It captures all type of errors into the `Cause` data type. ZIO uses `Cause[E]` to store the full story of failure, so its error model is **lossless**. It doesn't throw away information related to the failure result. So we can figure out exactly what happened during the operation of our effects.

It is important to note that `Cause` is the underlying data type for the ZIO data type, and we don't usually deal with it directly. Even though it is not a data type that we deal with very often, anytime we want, we can access the `Cause` data structure, which gives us total access to all parallel and sequential errors in our codebase.
It is important to note that `Cause` is the underlying data type for the ZIO data type, and we don't usually deal with it directly. Even though we do not deal with it very often, anytime we want, we can access the `Cause` data structure, which gives us total access to all parallel and sequential errors in our codebase.

## Cause Internals

ZIO uses a data structure from functional programming called a _semiring_ for the `Cause` data type. **It allows us to take a base type `E` that represents the error type and then capture the sequential and parallel composition of errors in a fully lossless fashion**.

The following snippet shows how the `Cause` is designed as a semiring data structure:
The following snippet shows how `Cause` is designed as a semiring data structure:

```scala
sealed abstract class Cause[+E] extends Product with Serializable { self =>
Expand Down Expand Up @@ -52,7 +52,7 @@ ZIO.failCause(Cause.empty).cause.debug
// Empty
```

Also, we can use the `ZIO#cause` to uncover the underlying cause of an effect. For example, we know that the `ZIO.succeed(5)` has no errors. So, let's check that:
Also, we can use `ZIO#cause` to uncover the underlying cause of an effect. For example, we know that `ZIO.succeed(5)` has no errors. So, let's check that:

```
ZIO.succeed(5).cause.debug
Expand All @@ -64,7 +64,7 @@ ZIO.attempt(5).cause.debug

### Fail

The `Fail` cause indicates the cause of an expected error of type `E`. We can create one using the `Cause.fail` constructor:
The `Fail` cause indicates the cause of an _expected error_ of type `E`. We can create one using the `Cause.fail` constructor:

```scala mdoc:compile-only
import zio._
Expand Down Expand Up @@ -100,7 +100,7 @@ myApp.cause.debug

### Die

The `Die` cause indicates a defect or in other words, an unexpected failure of type `Throwable`. Additionally, it contains the stack traces of the occurred defect. We can use the `Cause.die` to create one:
The `Die` cause indicates a defect, an _unexpected failure_ of type `Throwable`. It contains the stack trace of the defect that occurred. We can use `Cause.die` to create one:

```scala mdoc:compile-only
import zio._
Expand All @@ -109,7 +109,7 @@ ZIO.failCause(Cause.die(new Throwable("Boom!"))).cause.debug
// Die(java.lang.Throwable: Boom!,Trace(Runtime(2,1646479908),Chunk(<empty>.MainApp.run(MainApp.scala:3))))
```

If we have a bug in our code and something throws an unexpected exception, that information would be described inside a `Die`. Let try to investigate some ZIO codes that will die:
If we have a bug in our code and something throws an unexpected exception, that information would be described inside a `Die`. Let's try to investigate some ZIO code that will die:

```scala mdoc:compile-only
import zio._
Expand All @@ -121,11 +121,11 @@ ZIO.dieMessage("Boom!").cause.debug
// Stackless(Die(java.lang.RuntimeException: Boom!,Trace(Runtime(2,1646398246),Chunk(<empty>.MainApp.run(MainApp.scala:7)))),true)
```

It is worth noting that the latest example is wrapped by the `Stackless` cause in the previous example. We will discuss the `Stackeless` further, but for now, it is enough to know that the `Stackeless` include fewer stack traces for the `Die` cause.
It is worth noting that the latest example is wrapped by the `Stackless` cause in the previous example. We will discuss `Stackless` further, but for now, it is enough to know that `Stackless` includes fewer stack traces than the `Die` cause.

### Interrupt

The `Interrupt` cause indicates a fiber interruption which contains information of the _fiber id_ of the interrupted fiber and also the corresponding stack strace. Let's try an example of:
The `Interrupt` cause indicates a fiber interruption which contains information of the _fiber id_ of the interrupted fiber, and also the corresponding stack trace. Let's try an example of:

```scala mdoc:compile-only
import zio._
Expand All @@ -142,9 +142,9 @@ ZIO.never.fork

### Stackless

The `Stackless` cause is to store stack traces and execution traces. It has a boolean stackless flag which denotes that the ZIO runtime should print the full stack trace of the inner cause or just print the few lines of it.
The `Stackless` cause stores stack traces and execution traces. It has a boolean `stackless` flag which denotes whether the ZIO runtime should print the full stack trace of the inner cause or just print a few lines of it.

For example, the `ZIO.dieMessage` uses the `Stackless`:
For example, `ZIO.dieMessage` uses `Stackless`:

```scala mdoc:compile-only
import zio._
Expand All @@ -160,7 +160,7 @@ timestamp=2022-03-05T11:08:19.530710679Z level=ERROR thread=#zio-fiber-0 message
at <empty>.MainApp.run(MainApp.scala:3)"
```

While the `ZIO.die` doesn't use `Stackless` cause:
While `ZIO.die` doesn't use `Stackless` cause:

```scala mdoc:compile-only
import zio._
Expand All @@ -185,7 +185,7 @@ timestamp=2022-03-05T11:19:12.666418357Z level=ERROR thread=#zio-fiber-0 message

When we are doing parallel computation, the effect can fail for more than one reason. If we are doing two things at once and both of them fail then we actually have two errors. So, the `Both` cause stores the composition of two parallel causes.

For example, if we run two parallel fibers with `zipPar` and all of them fail, so their causes will be encoded with `Both`:
For example, if we run two parallel fibers with `zipPar` and all of them fail, their causes will be encoded with `Both`:

```scala mdoc:compile-only
import zio._
Expand All @@ -200,7 +200,7 @@ myApp.cause.debug
// Both(Fail(Oh uh!,Trace(Runtime(13,1646481219),Chunk(<empty>.MainApp.myApp(MainApp.scala:5)))),Stackless(Die(java.lang.RuntimeException: Boom!,Trace(Runtime(14,1646481219),Chunk(<empty>.MainApp.myApp(MainApp.scala:6)))),true))
```

Ir we run the `myApp` in the stack trace we can see two exception traces occurred on two separate fibers:
If we run the `myApp` effect, in the stack trace we can see two exception traces occurred on two separate fibers:

```scala
timestamp=2022-03-05T12:37:46.831096692Z level=ERROR thread=#zio-fiber-0 message="Exception in thread "zio-fiber-13" java.lang.String: Oh uh!
Expand All @@ -209,11 +209,11 @@ at <empty>.MainApp.myApp(MainApp.scala:5)
at <empty>.MainApp.myApp(MainApp.scala:6)"
```

Other parallel operators are also the same, for example, ZIO encode the underlying cause of the `(ZIO.fail("Oh uh!") <&> ZIO.dieMessage("Boom!"))` with `Both` cause.
Other parallel operators are also the sa 6093 me, for example, ZIO encodes the underlying cause of `(ZIO.fail("Oh uh!") <&> ZIO.dieMessage("Boom!"))` with the `Both` cause.

### Then

ZIO uses `Then` cause to encode sequential errors. For example, if we perform ZIO's analog of `try-finally` (e.g. `ZIO#ensuring`), and both of `try` and `finally` blocks fail, so their causes are encoded with `Then`:
ZIO uses `Then` cause to encode sequential errors. For example, if we perform ZIO's analog of `try-finally` (e.g. `ZIO#ensuring`), and both `try` and `finally` blocks fail, their causes are encoded with `Then`:

```scala mdoc:compile-only
import zio._
Expand Down
Loading
0