Skip to main content
Sifr eliminates runtime exceptions by making errors part of a function’s return type. When a function can fail, it declares Result[T, E] as its return type. The compiler then refuses to compile any call site that does not handle the error — you cannot accidentally ignore a failure the way you can with an uncaught exception in Python.

The Result Type

Result[T, E] is a built-in union that represents either a successful value (Ok(T)) or a failure (Err(E)). You never construct Ok or Err directly in Sifr source code — the compiler handles the wrapping for you.
  • A plain return value is automatically wrapped in Ok.
  • A raise statement inside a Result-returning function is mapped to Err.
raise inside a Result-returning function does not unwind the call stack. It is syntactic sugar for constructing and returning an Err variant. No exception propagates.

Custom Error Classes

Define your own error types by subclassing Error. Add typed fields to carry diagnostic information — the compiler treats them as plain structs.
You can define as many error types as you need. Each one is an independent type, so the compiler can distinguish them in try/except branches.

Handling Errors with try/except

Use try/except to consume a Result-returning function. Inside the try block, the return value is automatically unwrapped to its success type T. The except clause receives the typed error value.
If you call a Result-returning function without a try/except, the compiler emits an error. You must either handle the error or explicitly discard it with _ = ....

Fallible vs Infallible Conversions

Some conversions can fail and return Result, while others are guaranteed to succeed and return the value directly.

Division and Domain Errors

Use the same Result pattern for any operation that can fail due to invalid inputs.

Explicitly Discarding Results

If you intentionally do not need the result of a fallible call, assign it to _. This signals to the compiler that the discard is deliberate, not accidental.
Use explicit discard sparingly. Prefer handling the error so your program reacts correctly when something goes wrong in production.

Assertions

Use assert to express invariants that must hold at a specific point in your program. An assertion failure is a programmer error, not a recoverable runtime condition — it immediately aborts the program with a diagnostic message.
Reserve assert for internal correctness checks. Use Result and custom error types for anything that could fail due to external input or environment conditions.

Error Handling at a Glance

Python Developer Guide

See why recoverable exceptions become typed values in Sifr.

Rust Developer Guide

Map Sifr’s Result[T, E] syntax to Rust’s Result<T, E> model.