Gleam Let Assert

The let assert expression tells Gleam to match a pattern and panic if the match fails. It is a tool for situations where you are absolutely certain a value has a specific shape — and want the program to crash loudly if it does not.

Standard let vs let assert


Standard let — only works with irrefutable patterns:
──────────────────────────────────────────────────
let x = 42         // always succeeds — x matches any value
let #(a, b) = #(1, 2)  // always succeeds — structure is fixed

let assert — works with any pattern, panics if it fails:
──────────────────────────────────────────────────
let assert Ok(value) = might_return_error()
  // If result is Error(...), the program panics

When to Use let assert

Use let assert when you want to extract a value from a pattern that could theoretically fail — but you know from context that it will not. Common uses include test setup, startup configuration loading, and initializing known-good data.


let assert Use Cases
──────────────────────────────────────────────────
✓ Reading config values that must exist at startup
✓ Parsing data in test code where you control input
✓ Extracting from Result when failure means a bug
✗ Production code handling user input (use case instead)

Extracting from Option

import gleam/list

let numbers = [10, 20, 30]
let assert Ok(first) = list.first(numbers)
// first = 10

// If numbers were [], list.first returns Error(Nil)
// and the program would panic with a clear message

let assert Flow Diagram
──────────────────────────────────────────────────
list.first([10, 20, 30]) returns Ok(10)

let assert Ok(first) = Ok(10)
   ↓
Pattern Ok(first) matches Ok(10)? YES
   ↓
first = 10 ✓

If it returned Error(Nil):
let assert Ok(first) = Error(Nil)
   ↓
Pattern Ok(first) matches Error(Nil)? NO
   ↓
PANIC — program crashes with a message

Extracting from Result

import gleam/int

// Parsing a string we wrote ourselves — we know it's valid
let assert Ok(port) = int.parse("8080")
// port = 8080

let assert in Tests

Test code often uses let assert because test input is controlled — you wrote it yourself:

pub fn parse_config_test() {
  let assert Ok(config) = load_config("test_config.json")
  assert config.port == 8080
  assert config.host == "localhost"
}

If load_config fails during a test, a panic with a clear error message is exactly what you want — it stops the test immediately and tells you what went wrong.

let assert vs case


Comparison: let assert vs case
──────────────────────────────────────────────────
// With case (safe, handles both outcomes):
case int.parse(user_input) {
  Ok(n)      -> use_number(n)
  Error(Nil) -> show_error("Not a valid number")
}

// With let assert (panics on Error):
let assert Ok(n) = int.parse(user_input)
use_number(n)

The case version handles bad input gracefully. The let assert version crashes if the input is invalid. Choose case for user-provided data. Choose let assert only when failure truly represents a programming error, not a user error.

Tuple Destructuring with let assert

let data = #(200, "Success", True)

// Standard let works because the pattern is irrefutable:
let #(code, message, ok) = data
// code = 200, message = "Success", ok = True

// let assert works the same way for simple tuples:
let assert #(200, msg, _) = data
// msg = "Success"
// Panics if data is not #(200, ...)

Panic Messages

When let assert fails, Gleam prints a clear panic message that includes the file name and line number:


Panic Output Example
──────────────────────────────────────────────────
error: Assertion failed

  → src/main.gleam:14

  Pattern `Ok(n)` did not match value `Error(Nil)`

The program crashed here so you can fix the issue
before it causes silent failures elsewhere.

Summary


let assert Quick Reference
──────────────────────────────────────────────────
Syntax:   let assert Pattern = expression

Use when:
  • You control the input and know the pattern matches
  • A non-match would be a programming bug, not user error
  • Setting up test data

Avoid when:
  • Handling user input or external data
  • Production code where graceful error handling is needed
  → Use case expression instead

let assert is a deliberate choice: you are saying "I guarantee this matches — crash loudly if I am wrong." That loud crash is useful during development. In production systems handling untrusted input, a well-structured case expression is always the safer path.

Leave a Comment

Your email address will not be published. Required fields are marked *