Browse the docs

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#

silk
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#

silk
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#

silk
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#

silk
Success

The success case. It owns the produced value.

Field value#

silk
pub value: A

The owned success value.

Failure#

silk
Failure

The failure case. It owns the failure value.

Field error#

silk
pub error: F

The owned failure value.

Implementation Result<A, F>#

silk
impl<A, F> Result<A, F>

Associated function succeed#

silk
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#

silk
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#

silk
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#

silk
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#

silk
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#

silk
pub fn unwrapOr(
    self: Self,
    /// The value to return if `self` is a failure. It is dropped if `self` is a success.
    fallback: A,
  ) -> A

Returns 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#

silk
fallback: A

The 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.

View the source of this page