Skip to main content
Use ensure when your program should continue only after a value passes a check. A failed check returns an error. A successful check gives Forst more precise information about the value on the following lines. This keeps validation beside the code that depends on it. Use if x is ... when you want to choose a branch instead of returning early.

Stop when a check fails

Write ensure value is Condition() to check a value. Add or when you want to return a specific error. This drive function rejects a speed that is too high, then updates a shared position.
When the check fails, drive returns TooFast. position stays unchanged. position += speed runs only after the speed passes.
See Errors and Result for how to define named errors such as TooFast.
Forst provides conditions such as LessThan, Min, Present, and Ok. The is operator runs the condition and refines the value’s type after success. See the full list of constraints.

Exiting from main

main starts the process. A failed ensure there ends the process with exit status 1. There is no caller to return an error to, so or is not allowed. Write ensure !err when you only need that exit. Add a { ... } block when you want to log or clean up first. The block runs on failure. The process still exits afterward. This example calls drive, then stop. The first check has no block. The second prints a line if stop fails.
If drive fails, the program writes to stderr and exits. stop never runs. If stop fails, the program prints failed to stop: and the error, then exits. Nothing after that ensure in main runs.

Check for missing values

Use Nil() when a value must be absent. This works with nilable values such as pointers, Map, Array, and Error.
claim continues only when slot is nil. open then uses ensure !err or err, the short form of ensure err is Nil() or err. Both lower to the same Go if err != nil check. Pointer fields also support .Present() and .Nil(). Full optional value types such as T | Nil are still planned.

Use a successful Result value

Map lookups and other operations that may fail return Result(V, Error). Check for Ok() before using the successful value.
After ensure avail is Ok(), avail has the value type stored in the map. The next check can safely compare the requested quantity with it. Use the same pattern for function calls that return a Result.

Choose a branch after a check

Use if x is ... when both outcomes belong in the current function. Forst refines the value inside the matching branch.
The original type remains available outside the branch.

Keep checks explicit

Forst keeps validation visible in normal control flow. ensure returns an error. if selects a branch. Values are never silently coerced. This avoids common problems from other approaches.

Current limits

ensure and narrowing are experimental. Behavior and diagnostics are still maturing. See the roadmap.

Checks apply to the current value

A successful ensure or if check narrows the value at that point. Later reassignment or field changes may invalidate what the earlier check proved. See Type guards for a concrete example.
Narrowing reflects a single check at compile time. It does not lock or freeze the value at runtime.

Prefer simple variables

Narrowing after ensure works best with a simple variable such as ensure x is .... Paths such as ensure req.state is ... have partial support. Editor hover may show the condition while later code still sees the original field type.

Narrowing after branches

Narrowing inside an if branch may end with that branch. Code after the full chain can see the earlier type. Branch merging will improve as union type support expands.

Map lookups use Result

Forst map lookups return Result(V, Error). Go style comma assignment such as v, ok := m[k] is unsupported. Use ensure avail is Ok() before reading the value.

Optional values are partial

Full optional value types such as T | Nil are planned. Use nil with nilable types, ensure ... is Nil(), or .Present() and .Nil() on pointer fields.

Generated Go

Generated Go uses ordinary conditionals and error returns for ensure. A custom failure after or becomes a named Go error type. In main, a failed check exits the process instead of returning.

Examples

See the ensure and narrowing examples on GitHub Continue with named errors or reusable conditions.

Errors and Result

Nominal error types and structured failures.

Type guards

User-defined predicates for domain rules.