Lesson 14 of 17

The Result Type

Error Handling with Result

Gleam has no exceptions. Instead, functions that can fail return a Result type:

pub type Result(value, error) {
  Ok(value)
  Error(error)
}

A Result is either Ok with a success value, or Error with an error value.

Returning Results

fn divide(a: Int, b: Int) -> Result(Int, String) {
  case b {
    0 -> Error("division by zero")
    _ -> Ok(a / b)
  }
}

Handling Results

Use case to handle both outcomes:

case divide(10, 3) {
  Ok(value) -> io.println("Result: " <> int.to_string(value))
  Error(msg) -> io.println("Error: " <> msg)
}

The Result Module

The gleam/result module provides functions for working with results:

import gleam/result

// Transform the Ok value
result.map(Ok(5), fn(x) { x * 2 })           // Ok(10)
result.map(Error("oops"), fn(x) { x * 2 })   // Error("oops")

// Chain operations that return Results
result.try(Ok(5), fn(x) { Ok(x * 2) })       // Ok(10)
result.try(Error("oops"), fn(x) { Ok(x * 2) }) // Error("oops")

// Provide a default value
result.unwrap(Ok(5), 0)          // 5
result.unwrap(Error("oops"), 0)  // 0

Chaining with result.try

result.try is key for chaining operations. If any step returns Error, the chain short-circuits:

fn process() -> Result(Int, String) {
  result.try(parse_int("42"), fn(x) {
    result.try(divide(x, 2), fn(y) {
      Ok(y + 1)
    })
  })
}

This nesting can get deep, which is why Gleam provides the use expression (next lesson).

Your Task

Write a function called safe_divide that takes two integers and returns Result(Int, String). It should return Error("division by zero") when the divisor is 0, otherwise Ok with the result.

Write a function called try_divide_and_add that divides a by b, then adds c to the result using result.map. Print the results for (10, 2, 3) and (10, 0, 3).

Gleam runtime loading...
Loading...
Click "Run" to execute your code.