Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Nil

nil represents the absence of a value.

It is its own type with a single value. println(nil) prints nil, and it interpolates as nil inside a string. The only methods it has are to_string() and the is_* type predicates — and note that there is no is_nil(), so test for nil with == nil.

Checking for nil

Use equality and conditional match / guards:

import std:println

value = nil

match { value == nil => { println("Value is nil") } }
match { value != nil => { println("Value exists") } }
# Value is nil

nil is not “falsy”: !nil is a type error (Cannot apply logical NOT to nil), and nil || "default" is a type error too. Comparing is the only test.

Returning nil for “not found”

Because there is no exception mechanism, returning nil is the normal way to say “nothing here”:

import std:println

# The keys are quoted: a map literal that is the whole body of a match arm would
# otherwise be parsed as a block.
get_user = |id| match id {
    1 => {"name": "Alice", "age": 30},
    2 => {"name": "Bob", "age": 25},
    _ => nil,
}

user = get_user(1)
match { user != nil => println("Found: ${user:name}"), _ => println("User not found"), }
# Found: Alice

user = get_user(9)
match { user != nil => println("Found: ${user:name}"), _ => println("User not found"), }
# User not found

A match that has no matching arm also evaluates to nil, so an incomplete match yields nil rather than raising.

Nil in collections

Lists

import std:println

items = [1, nil, 3, nil, 5]
non_nil = items::filter(|x| x != nil)
println(non_nil)  # [1, 3, 5]

Maps

A missing key does not read as nil — it raises Key not found and terminates the program. Use ::get() when the key may be absent:

import std:println

user = {name: "Alice", age: 30}

# This would abort the script:
# email = user:email   # Error: Key not found: Key 'email' not found in map

email = user::get("email")
println(email)  # nil

match { email != nil => println("Email: ${email}"), _ => println("No email provided"), }
# No email provided

get() accepts a default as its second argument, which is usually clearer than checking for nil afterwards:

import std:println

user = {name: "Alice"}
println(user::get("email", "none"))  # none

Note that a key whose stored value really is nil is indistinguishable from a missing key when you use get() with no default — use ::contains() if that distinction matters.

Default values

Use match for defaults. There is no || fallback idiom, because || requires boolean operands:

import std:println

title = nil
title = match { title != nil => title, _ => "Mr./Ms.", }
println(title)  # Mr./Ms.

See Also