From 796ccdc4b9e5c72793e3eb2a952d64806b8618ae Mon Sep 17 00:00:00 2001 From: Bruce Eckel Date: Thu, 25 Jul 2024 22:09:00 -0600 Subject: [PATCH] edit pass #bruce #time 15m --- Chapters/07_Composability.md | 36 +++++++++++++++++++----------------- 1 file changed, 19 insertions(+), 17 deletions(-) diff --git a/Chapters/07_Composability.md b/Chapters/07_Composability.md index ae3b1807..b22858cc 100644 --- a/Chapters/07_Composability.md +++ b/Chapters/07_Composability.md @@ -16,12 +16,12 @@ Issues that complicate composition include: - Failures - Async - Blocking -- Managed resource +- Managed resources - Cancellation - Either-ness - Environmental requirements -These concepts and their competing solutions will be expanded on and contrasted throughout this chapter. +These concepts and their competing solutions are expanded and contrasted throughout this chapter. In this chapter, we use several pre-defined functions. The implementations are deliberately hidden to highlight the surprising nature of executing Effects and to maintain focus on composability. @@ -165,12 +165,12 @@ import scala.concurrent.Future The original asynchronous datatype in Scala has several undesirable characteristics: -- It starts executing immediately -- Cleanup is not guaranteed -- It fails with Exceptions -- It needs `ExecutionContext`s to be constantly passed +- It starts executing immediately. +- Cleanup is not guaranteed. +- It fails with Exceptions. +- It needs `ExecutionContext`s to be constantly passed. -`getHeadLine` is one of our hidden-implementation functions that returns a Future: +`getHeadLine` is one of our hidden-implementation functions that returns a `Future`: ```scala 3 mdoc:compile-only import zio.* @@ -181,10 +181,10 @@ val future: Future[String] = getHeadLine() By wrapping this in `ZIO.from`, we can: -- Defer execution -- Attach finalizer behavior -- Customize the failure type -- Get the required `ExecutionContext` +- Defer execution. +- Attach finalizer behavior. +- Customize the failure type. +- Get the required `ExecutionContext`. ```scala 3 mdoc:silent import zio.* @@ -223,7 +223,7 @@ def run = ## Option `Option` indicates that a value might not be available. -It does not deal with asynchronicity, failure types, or anything else. +It does not deal with things like asynchronicity or failure types. Execution is not deferred, and it cannot interrupt the code producing the `Option` values. ```scala 3 mdoc:silent @@ -318,7 +318,7 @@ def run = ## AutoCloseable Java & Scala provide the `AutoCloseable` interface for defining finalizer behavior for objects. -This is an improvement over manual management, but its static scoping makes it clunky to use. +This is an improvement over manual management, but its static scoping limits its usability. ```scala 3 mdoc:invisible import zio.* @@ -419,6 +419,7 @@ val file: AutoCloseable = openFile("file1") ``` Since `AutoCloseable` is a trait that can be implemented by arbitrary classes, we can't rely on `ZIO.from` to automatically manage this conversion. +`ZIO.from` cannot guess what that implementation might be or how to clean it up. Instead, we use `ZIO.fromAutoCloseable`: ```scala 3 mdoc:silent @@ -433,7 +434,7 @@ def openFileZ(path: String) = ``` Now the `ZIO` runtime manages the lifecycle of this object via the `Scope` mechanism. -For a more thorough discussion of this, see the [ZIO documentation](https://effectorientedprogramming.com/resources/zio/docs). +For a more thorough discussion of `Scope`, see the [ZIO documentation](https://effectorientedprogramming.com/resources/zio/docs). Let's open a `File` and see if it contains a topic of interest: @@ -471,7 +472,7 @@ def run = .get ``` -You can see that each new file means an additional level of code nesting. +You can see that each new file creates an additional level of code nesting. Contrast this with: ```scala 3 mdoc:runzio @@ -708,7 +709,7 @@ val researchHeadline = Look at how straightforward this code is. You can now build complex real-world applications that flow cleanly, because you're using an Effect System. -Let's step through all possible scenarios for our application. +We'll step through all possible scenarios for our application. ### Headline Not Available @@ -819,7 +820,8 @@ def run = strictResearch ``` Repeating is a form of composability, because you are composing a program value with itself along with a delay. -Now that we have a nice, single-shot workflow that analyzes the current headline, we can make it run every day: +Now we have a nice, single-shot workflow that analyzes the current headline. +We can make it run every day: ```scala 3 mdoc:silent val daily =