silk.core.result.
Completed outcomes that hold a success value or a failure value as ordinary data.
When to use#
Use Result when a caller must keep, return, or inspect an outcome as a value, and the
failure needs a reason. Use silk.core.option.Option when "no value" needs no reason. Use an
effect failure channel (!) when the failure must propagate with fail and run.
Use map to transform a success, mapError to transform a failure, flatMap to chain a
step that can also fail, and unwrapOr to get a plain value with a fallback.
Details#
Result<A, F> is a union with the variants Success and Failure. Each combinator
consumes the result. The selected value moves into the output. A value that the operation does
not use is dropped.
A Result is completed data. It does not run, it needs no provider, and it does not propagate.
Effect.result runs an effect and gives its outcome as a Result.
Examples#
Chain two steps that can fail#
import silk.core.result { Result }
fn half(value: i32) -> Result<i32, string<'static>> {
if value % 2 != 0 {
return Result<i32, string<'static>>.failResult("odd")
}
return Result<i32, string<'static>>.succeed(value / 2)
}
pub fn main() -> i32 {
let quarter = Result<i32, string<'static>>.succeed(80)
|> Result<i32, string<'static>>.flatMap<i32>(half)
|> Result<i32, string<'static>>.flatMap<i32>(half)
|> Result<i32, string<'static>>.unwrapOr(-1)
let failed = Result<i32, string<'static>>.succeed(6)
|> Result<i32, string<'static>>.flatMap<i32>(half)
|> Result<i32, string<'static>>.flatMap<i32>(half)
|> Result<i32, string<'static>>.unwrapOr(-1)
if quarter != 20 || failed != -1 {
return 1
}
return 0
}Import as Result with import silk.core.result { Result }.
Public declarations: 1.
Result#
pub union Result<A, F>A completed outcome that owns a success value of type A (Success) or a failure value of
type F (Failure).
When to use#
Use Result as a return type when an operation can fail and the caller must handle the failure
as a value. Effect.result also gives the outcome of an effect as a Result.
Details#
Create values with succeed and failResult. A match on move result consumes the
result. A match on a borrow keeps the result available.
Examples#
Handle both cases with match#
import silk.core.result { Result }
import silk.num.u8
fn parseDigit(byte: u8) -> Result<i32, u8> {
if byte < 48 || byte > 57 {
return Result<i32, u8>.failResult(byte)
}
return Result<i32, u8>.succeed(byte - 48 |> u8.toI32)
}
pub fn main() -> i32 {
let digit = match move parseDigit(55) {
Result<i32, u8>.Success { value } => value
Result<i32, u8>.Failure { error } => -1
}
if digit != 7 {
return 1
}
return 0
}Success#
SuccessThe success case. It owns the produced value.
Field value#
pub value: AThe owned success value.
Failure#
FailureThe failure case. It owns the failure value.
Field error#
pub error: FThe owned failure value.
Implementation Result<A, F>#
impl<A, F> Result<A, F>Associated function succeed#
pub fn succeed(value: A) -> Result<A, F>Returns a successful Result<A, F> that owns value.
Details#
Write both type arguments, as in Result<i32, string<'static>>.succeed(1). No argument gives
the compiler the failure type F.
Associated function failResult#
pub fn failResult(error: F) -> Result<A, F>Returns a failed Result<A, F> that owns error.
Details#
Write both type arguments, as in Result<i32, string<'static>>.failResult("empty"). No
argument gives the compiler the success type A. The name is not fail because fail is a
keyword.
Method map#
pub fn map<B>(self: Self, transform: once fn(A) -> B) -> Result<B, F>Returns transform(value) as a success if self is a success. Returns the same failure if
self is a failure.
When to use#
Use map when the transform always succeeds. Use flatMap when the transform can also
fail. Use mapError to change the failure value.
Details#
transform runs one time for a success and does not run for a failure. This function
consumes self. It changes only the success type.
Method mapError#
pub fn mapError<G>(self: Self, transform: once fn(F) -> G) -> Result<A, G>Returns transform(error) as a failure if self is a failure. Returns the same success if
self is a success.
When to use#
Use mapError to convert a failure into the failure type of the caller, or to add context to
a failure. flatMap needs the same failure type in each step, so use mapError to align
the types first.
Details#
transform runs one time for a failure and does not run for a success. This function consumes
self. It changes only the failure type.
Method flatMap#
pub fn flatMap<B>(self: Self, transform: once fn(A) -> Result<B, F>) -> Result<B, F>Returns the result that transform produces for a success. Returns the same failure if self
is a failure.
When to use#
Use flatMap to chain steps where each step can fail. The output is one Result<B, F>, not a
nested Result<Result<B, F>, F>. Use map when the step cannot fail.
Details#
transform runs one time for a success and does not run for a failure. The first failure
stops the chain. This function consumes self.
Gotchas#
transform must return the same failure type F. If the steps use different failure types,
convert them with mapError first.
Method unwrapOr#
pub fn unwrapOr(
self: Self,
/// The value to return if `self` is a failure. It is dropped if `self` is a success.
fallback: A,
) -> AReturns the success value. Returns fallback if self is a failure.
When to use#
Use unwrapOr when one default value is correct for each failure. Use match when the
failure value controls the recovery or the caller must keep it.
Details#
This function consumes self and fallback. It returns one value. It drops the failure value
or the unused fallback.
Gotchas#
The failure value is dropped without a report. The caller evaluates fallback before the
call, also when self is a success.
Parameter fallback#
fallback: AThe value to return if self is a failure. It is dropped if self is a success.
Category: Core.
Profiles: aarch64-apple-darwin, aarch64-unknown-linux-gnu, aarch64-unknown-linux-gnu-no-libc, x86_64-unknown-linux-gnu, x86_64-unknown-linux-gnu-no-libc, wasm32-unknown-unknown, wasm32-wasip1, wasm32-wasip2.