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

Find and validate collection values

Option[T] has two variants: Some(T) and Nothing. Some, Nothing, Ok, and Err are built in and need no type prefix. Nothing belongs to one concrete option type; it is not a universal null.

def first_positive(values: list[i64]) -> Option[i64]:
    for value in values:
        if value > 0:
            return Some(value)
    Nothing

def main() -> Result[(), AllocError | IoError]:
    for values in [[-1, 0]?, [-1, 42]?]?:
        match first_positive(values):
            case Some(value):
                print(value)?
            case Nothing:
                print("not found")?
    Ok(())
not found
42

Use Result[T, E] when the absent result has an explanation. Its variants are Ok(T) and Err(E). This example intentionally maps arithmetic errors to explanatory strings; a numeric API can instead preserve the builtin error types. The return signature supplies both types:

def divide(left: i64, right: i64) -> Result[i64, str]:
    if right == 0:
        return Err("division by zero")
    result = checked:
        left // right
    match result:
        case Ok(value):
            Ok(value)
        case Err(OverflowError(_)):
            Err("quotient out of range")
        case Err(ZeroDivisionError()):
            Err("division by zero")

def main() -> Result[(), AllocError | IoError]:
    for result in [divide(8, 2), divide(8, 0)]?:
        match result:
            case Ok(value):
                print(value)?
            case Err(message):
                print(message)?
    Ok(())
4
division by zero

Validate text in a collection

For an operation that can fail but has no success data, return Result[(), E] and construct success with Ok(()):

def validate(name: str) -> Result[(), str]:
    if len(name) == 0:
        return Err("name is empty")
    Ok(())

def main() -> Result[(), AllocError | IoError]:
    for result in [validate("Plenty"), validate("")]?:
        match result:
            case Ok(_):
                print("valid")?
            case Err(message):
                print(message)?
    Ok(())
valid
name is empty

Unit is a real success payload, distinct from the absence represented by Nothing. Option[()] also works. Standalone unit bindings and unit parameters remain unsupported. User-defined enum variants still use their enum’s prefix, even if a variant happens to be named Ok or Some.