Same Shape, Different Contract
If you know Python, start by keeping the surface model and changing the failure model. Sifr tries to make illegal states visible before a binary is built: missing values are typed, fallible calls returnResult, and values crossing ownership or task boundaries must be explicit.
What Carries Over
You still writedef, class, if, for, list and dict literals, comprehensions, f-strings, match, async def, and await. The goal is not to make you learn a new surface grammar before you can write useful programs.
describe promises str, every path must return str.
What Changes At Compile Time
Sifr turns several Python runtime surprises into compile-time obligations:- a dictionary lookup that might miss returns
V | None; - a fallible function returns
Result[T, E]; - a parameter is immutable unless marked
mut; - a value is borrowed by default unless a function asks for
own; - a spawned task can only capture values that are owned and sendable.
Sifr docs are the source of truth for Sifr semantics. Python references are useful for syntax vocabulary, but they do not define Sifr’s type, ownership, error, or package model.
Common Surprises
Type hints are not hints
Type hints are not hints
Sifr annotations are checked before the program runs. Treat them as part of the language, not as documentation for a separate runtime.
Exceptions do not unwind normal errors
Exceptions do not unwind normal errors
raise inside a Result-returning function produces an error value. try/except handles that value explicitly.Imports use the Sifr namespace
Imports use the Sifr namespace
Use
from sifr.collections import Counter, not import collections. Supported stdlib-style modules live under sifr.*; see the collections import example.Calling installed Python packages is explicit
Calling installed Python packages is explicit
Use
sifr.python when you intentionally embed CPython and call packages from a uv-created environment. Configure the root package’s [python] and [trust] tables first; see Embedded Python Interop.Mutation is explicit
Mutation is explicit
Use
mut when a function should mutate a borrowed parameter, and own mut when it should take ownership and mutate the value.Where To Go Next
Mental Model Shift
Follow the practical path from Python habits to Sifr’s compile-time model.
Ownership and Mutability
Learn
mut, own, and borrow-by-default rules.Error Handling
See how
Result and try/except replace recoverable exceptions.Embedded Python Interop
Call installed Python packages through explicit environment and trust boundaries.
