# `MonEx.Result`
[🔗](https://github.com/youroff/monex/blob/v0.2.1/lib/monex/result.ex#L1)

A `Result` represents the outcome of an operation that can fail:

  * `ok(value)` — success, carrying a value
  * `error(reason)` — failure, carrying a reason

The runtime representation is just an idiomatic Elixir tuple
(`{:ok, value}` or `{:error, reason}`), so MonEx slots in on top of any
function that already returns those.

# `t`

```elixir
@type t(res, err) :: {:ok, res} | {:error, err}
```

Result type.
`ok(res)` and `error(err)` expand to `{:ok, res}` and `{:error, err}` respectively.

# `collect_error`

```elixir
@spec collect_error([t(res, err)]) :: [err] when res: any(), err: any()
```

Walks a list of `Result`s and returns the unwrapped error reasons,
preserving order.

## Examples
    iex> [ok(1), error("oops")] |> collect_error
    ["oops"]

# `collect_ok`

```elixir
@spec collect_ok([t(res, any())]) :: [res] when res: any()
```

Walks a list of `Result`s and returns the unwrapped success values,
preserving order.

## Examples
    iex> [ok(1), error("oops")] |> collect_ok
    [1]

# `error`
*macro* 

Constructor macro: `error(err)` expands to `{:error, err}`. Works in
both expressions and patterns.

# `fallback`

```elixir
@spec fallback(t(res, err), t(res, err) | (err -&gt; t(res, err))) :: t(res, err)
when res: any(), err: any()
```

Returns the input as-is if it is `ok()`. If `error()`, returns the
second argument — either a `Result` directly, or a 1-arity function
receiving the error and returning a `Result`.

## Examples
    iex> ok(5) |> fallback(fn _ -> 1 end)
    ok(5)

    iex> error("WTF") |> fallback(fn m -> ok("#{m}LOL") end)
    ok("WTFLOL")

    iex> error("WTF") |> fallback(ok(5))
    ok(5)

# `is_error`

```elixir
@spec is_error(t(any(), any())) :: boolean()
```

Returns `true` if the argument is `error()`, `false` if `ok()`.

## Examples
    iex> is_error(error("Error"))
    true

    iex> is_error(ok(5))
    false

# `is_ok`

```elixir
@spec is_ok(t(any(), any())) :: boolean()
```

Returns `true` if the argument is `ok()`, `false` if `error()`.

## Examples
    iex> is_ok(ok(5))
    true

    iex> is_ok(error("Error"))
    false

# `ok`
*macro* 

Constructor macro: `ok(res)` expands to `{:ok, res}`. Works in both
expressions and patterns.

# `partition`

```elixir
@spec partition([t(res, err)]) :: %{ok: [res], error: [err]}
when res: any(), err: any()
```

Splits a list of `Result`s into a map with `:ok` and `:error` keys
pointing at the unwrapped values. Both keys are always present, even
when one bucket is empty.

## Examples
    iex> [ok(1), error("oops"), ok(2)] |> partition
    %{ok: [1, 2], error: ["oops"]}

    iex> [ok(1)] |> partition
    %{ok: [1], error: []}

# `retry`
*macro* 

Re-runs the body block while it returns `error(_)`. The first `ok(_)`
short-circuits and is returned; if every attempt fails, the last
`error(_)` is returned.

## Options
  * `:n` — number of retries to attempt after the initial call (default: `5`)
  * `:delay` — milliseconds to sleep between attempts (default: `0`)

## Example
    result = retry n: 3, delay: 3000 do
      remote_service()
    end

Calls `remote_service()` up to 4 times (1 initial + 3 retries) with a
3-second pause between attempts.

# `try_result`
*macro* 

Evaluates `exp`, normalising the outcome into a `Result`:

  * a raised exception becomes `error(...)`,
  * a `Result` (`ok(_)` or `error(_)`) returned by `exp` is passed
    through unchanged,
  * any other value `x` becomes `ok(x)`.

## Modes
  * `:full` (default) — `error(...)` carries the exception struct
  * `:message` — `error(...)` carries the exception message string
  * `:module` — `error(...)` carries the exception module

## Examples
    iex> try_result do
    ...>   5 + 5
    ...> end
    ok(10)

    iex> try_result do
    ...>   raise ArithmeticError, message: "bad argument"
    ...> end
    error(%ArithmeticError{message: "bad argument"})

    iex> try_result :message do
    ...>   raise ArithmeticError, message: "bad argument"
    ...> end
    error("bad argument")

    iex> try_result :module do
    ...>   raise ArithmeticError, message: "bad argument"
    ...> end
    error(ArithmeticError)

# `unwrap`

```elixir
@spec unwrap(t(res, err), res | (err -&gt; res)) :: res when res: any(), err: any()
```

Returns `x` if the argument is `ok(x)`. Otherwise consults the second
argument:

  * a 1-arity function — called with the error term; its return is returned
  * any other non-`nil` value — returned as-is
  * `nil` (the default, when no fallback is supplied) — re-raises the error term

## Examples
    iex> unwrap(ok(5))
    5

    iex> unwrap(error(:uh_oh), fn _ -> 10 end)
    10

    iex> unwrap(error(:uh_oh), 10)
    10

# `unwrap_option`

```elixir
@spec unwrap_option(t(res, any())) :: MonEx.Option.t(res) when res: any()
```

Converts a `Result` into an `Option`: `ok(val)` becomes `some(val)`,
`error(_)` becomes `none()`. Useful when you only care whether a value
is present and want to drop the error reason.

## Examples
    iex> unwrap_option(ok(5))
    {:some, 5} # same as some(5)

    iex> unwrap_option(error(:uh_oh))
    {:none} # same as none()

---

*Consult [api-reference.md](api-reference.md) for complete listing*
