Chapter 11: Optional and Result, built
Chapter 11 meets two small containers for uncertainty: Optional, a box that holds a value or none, and Result, a box that holds success or an error. Divide asks safeDivide for a / b and gets back a Result of (Integer, String) rather than a runtime exception - isOk()/ok() on success, isError()/error() on failure, and the compiler refuses any read that skips the matching check. The IDE's own tools make safeDivide's and Div's whole structure; Surround With folds the division itself under an if ... else head before the real branches are typed in, and Analyse ▸ Effective API then reads Result's own surface before the program runs. To play it in the IDE: Help > Lessons > Writing code…, or ek9 -ide -lesson book-optional-result.
What you'll build
The lesson builds this program from a file holding only its module line - the finished file, as the book prints it.
#!ek9 defines module book.divide defines function safeDivide() as pure -> a as Integer b as Integer <- rtn <- Result() of (Integer, String) if b == 0 rtn: rtn.asError("cannot divide by zero") else rtn: rtn.asOk(a / b) defines program Div() stdout <- Stdout() good <- safeDivide(10, 2) if good.isOk() stdout.println(`Answer: ${good.ok()}`) bad <- safeDivide(10, 0) if bad.isError() stdout.println(`Cannot: ${bad.error()}`)
Step 1: safeDivide — a pure function returning Result
Choose Code > New Construct > Function…
safeDivide is the function's name. Add two parameters, a and b, both Integer, set Returns to Result of (Integer, String), and tick pure. Choose Preview.
The preview shows safeDivide about to be written, pure, a and b in and Result of (Integer, String) out. Choose Apply.
Select the stub, from <- rtn as Result of (Integer, String)? down to its //AI line, and type a single, unguarded division - the next part shows the compiler why that is not enough. Saves when typed.
Step 2: Divide by zero, with Surround With
Put the caret on the division line, right-click - or choose Refactor > Refactor This… - and choose Surround With ▸ if ... else.
Select the stub, from surroundGuard <- Boolean(true) down to its //AI line, and type the real check: b == 0 is the error path the if branch now reports, dividing is what the else branch does instead. Saves when typed.
Step 3: The program
Choose Code > New Construct > Program…
Div is the program's name - no application to bind, no parameters, nothing injected. Type Div and choose Preview.
The preview shows Div about to be written. Choose Apply.
Select the stub, from ready <- true down to its //AI line, and type Div's whole job: call safeDivide twice, reading the answer only after isOk(), and the error only after isError(). Saves when typed.
Step 4: Read Result's effective API
Select good, on the line that declares it, then choose Analyse ▸ Effective API: cursor-anchored, the same way Pipeline read chapter 12's stream before it ran.
The pane draws Result of (Integer, String)'s own surface: its Constructors - Result() and Result(ok, error) - then its Methods and Operators, each section counted. Among the methods are the six safeDivide and Div called by name - asOk and asError, which fill the box, and isOk, isError, ok and error, which read it safely - alongside what every EK9 type carries, such as ? for set and $ for a string form.
Step 5: Run it
Choose Run > Run Program…
The project's only program is already chosen. Choose Run.
Answer: 5, then Cannot: cannot divide by zero - the first call succeeded, the second was refused before it ever divided. Choose Close.
The result
Divide.ek9 now reads exactly as chapter 11 of Getting Started with EK9 shows it: a pure function that returns a Result rather than risk a division by zero, and a program that only ever reads it after checking which it got. Surround With folded the division itself under an if ... else head before the real condition and branches were typed in; Analyse ▸ Effective API then read Result of (Integer, String)'s own surface - the same surface ek9_query_effective_api answers for an AI assistant, a cursor position traded for a file and a line.
Where this lesson comes from
- For AI assistants - the MCP tool
ek9_new_construct,ek9_surround_with,ek9_add_program,ek9_query_effective_api.














