Result values and operations
Result<TValue, TError> represents expected failure as an ordinary value. It is a built-in source type
backed by the E#-authored CLR value type Esharp.Stdlib.Result`2; E# and C# therefore exchange the
same closed generic struct without an adapter.
Representation
Section titled “Representation”ResultType = "Result" "<" Type "," Type ">" .ResultConstructor = "ok" "(" Expr ")" | "error" "(" Expr ")" .ResultCaseView = ".ok" "(" identifier ")" | ".err" "(" identifier ")" .The value has one discriminant and two payload slots:
pub struct Result<TValue, TError> { pub IsOk: bool pub Value: TValue pub Error: TError}It is a value struct: assignment copies it; it has no identity; and construction does not allocate. The
variant invariant is IsOk iff Value is meaningful, and !IsOk iff Error is meaningful. The
compiler’s ok / error intrinsics initialize the discriminant and the selected payload directly.
Construction and access
Section titled “Construction and access”union ParseError { malformed, outOfRange }
func parse(text: string) -> Result<int, ParseError> { if text.Length == 0 { return error(.malformed) } return ok(int.Parse(text))}The expression’s contextual Result<T, E> type determines whether a dot case in error(.malformed)
is a valid error value. A program may also write the explicit static factory:
let success = Result.Ok<int, string>(42)let failure = Result.Error<int, string>("bad input")Result<T, E> and the arity-zero static Result factory coexist by arity keying.
The factory is an ordinary CLR static surface for explicit type arguments and C# interop; ok and error
are the idiomatic E# construction forms.
| Accessor | Result |
|---|---|
.IsOk | stored discriminant |
.IsError | synthesized negation of IsOk |
.Value | success payload; throws InvalidOperationException on error |
.Error | error payload; throws InvalidOperationException on success |
Case views and combinators
Section titled “Case views and combinators”A match over .ok(value) and .err(error) is exhaustive and projects the appropriate payload:
func label(r: Result<int, string>) -> string = match r { .ok(value) => "value {value}" .err(error) => "error {error}"}The ten Result combinators are value-receiver methods. They never mutate the input Result; each
returns a transformed or observed value.
| Method | Result |
|---|---|
Map(f) / MapErr(f) | transforms only success / error payload |
Bind(f) | chains a success into another Result |
Match(ok, err) | folds both cases to one output type |
Inspect(f) / InspectErr(f) | observes one case and returns the original result |
UnwrapOr(x) / UnwrapOrElse(f) | returns a success value or fallback |
Unwrap() / UnwrapErr() | returns a payload or throws on the opposite case |
Generic inference flows through a receiver and lambda body, so r.Map((x) => x + 1) closes the new
success type from the lambda result. Unwrap and direct .Value are deliberate exceptional escape
hatches; normal expected-failure flow uses match, combinators, or postfix ?.
See also
Section titled “See also”- Errors — complete error-model overview.
- Propagation with
?— early error return as an expression operator. - Pattern matching — exhaustiveness and case-view binding.