Try

Try := [Ok(ok), Err(err)]
parser_for : _
encoder_for : _
is_ok : Try(_ok, _err) -> Bool

Returns Bool.True if the result indicates a success, else returns Bool.False.

expect Try.Ok(5).is_ok()
is_err : Try(_ok, _err) -> Bool

Returns Bool.True if the result indicates a failure, else returns Bool.False.

expect Try.Err("uh oh").is_err()
from_interpolation : Str, Iter((interpolated, Str)) -> Try(ok, err)
    where [
        ok.from_interpolation : Str, Iter((interpolated, Str)) -> Try(ok, err),
    ]

Forwards interpolated string literal assembly through an inner type whose from_interpolation method returns the same Try.

ok_or : Try(ok, _err), ok -> ok

If the result is Ok, returns the value it holds. Otherwise, returns the given default value.

Note: This function should be used sparingly, because it hides that an error happened, which will make debugging harder. Prefer using ? to forward errors or handle them explicitly with match.

expect Try.Err("uh oh").ok_or(42) == 42

expect Try.Ok(7).ok_or(42) == 7
err_or : Try(_ok, err), err -> err

If the result is Err, returns the value it holds. Otherwise, returns the given default value.

expect Try.Err("uh oh").err_or("fallback") == "uh oh"

expect Try.Ok(7).err_or("fallback") == "fallback"
map_ok : Try(a, err), (a -> b) -> Try(b, err)

If the result is Ok, transforms the value it holds by running a conversion function on it. Then returns a new Ok holding the transformed value. If the result is Err, this has no effect. Use Try.map_err to transform an Err.

expect Try.Ok(12.I64).map_ok(|n| -n) == Ok(-12)

expect {
	err : Try(I64, Str)
	err = Err("yipes!")
	err.map_ok(|n| -n) == Err("yipes!")
}

Functions like map are common in Roc; see for example List.map and Set.map.

map_ok! : Try(a, err), (a => b) => Try(b, err)

Like Try.map_ok, but the transform function is effectful. If the argument is an Ok, the effect is run and its return value is wrapped in a new Ok. If the result is Err, the effect is not run and the Err is returned unchanged.

artist_try.map_ok!(|a| SQL.query!("SELECT * FROM albums WHERE artist_id = ?", [a.id]))
map_err : Try(ok, a), (a -> b) -> Try(ok, b)

If the result is Err, transforms the value it holds by running a conversion function on it. Then returns a new Err holding the transformed value. If the result is Ok, this has no effect. Use Try.map_ok to transform an Ok.

expect [].last().map_err(|_| ProvidedListIsEmpty) == Err(ProvidedListIsEmpty)

expect [4].last().map_err(|_| ProvidedListIsEmpty) == Ok(4.0)
map_err! : Try(ok, a), (a => b) => Try(ok, b)

Like Try.map_err, but the transform function is effectful. If the argument is an Err, the effect is run and its return value is wrapped in a new Err. If the result is Ok, the effect is not run and the Ok is returned unchanged.

# Log the failure to the database only when the request errored.
request.map_err!(|e| SQL.execute!("INSERT INTO errors (message) VALUES (?)", [e.message]))
map_both : Try(a, b), (a -> c), (b -> d) -> Try(c, d)

Transforms whichever value this result holds, by running one conversion function on an Ok and a different one on an Err. Only the function matching the variant is run. Use Try.map_ok or Try.map_err to transform just one variant, and Try.catch when both should produce the same type.

expect {
	ok : Try(I64, Str)
	ok = Ok(12)
	ok.map_both(|n| -n, |_| Failed) == Ok(-12)
}

expect {
	err : Try(I64, Str)
	err = Err("uh oh")
	err.map_both(|n| -n, |_| Failed) == Err(Failed)
}
map_both! : Try(a, b), (a => c), (b => d) => Try(c, d)

Like Try.map_both, but the transform functions are effectful. Only the effect matching the variant this result holds is run; the other is not.

request.map_both!(|ok| Log.info!("succeeded: ${ok}"), |e| Log.warn!("failed: ${e}"))
map2 : Try(a, err), Try(b, err), (a, b -> c) -> Try(c, err)

Combines two results by running a function on both Ok values. If either is an Err, that Err is returned instead and the function is not run. When both are Err, the first one wins.

expect Try.map2(Try.Ok(2.I64), Try.Ok(3), |a, b| a * b) == Ok(6)

expect {
	err : Try(I64, Str)
	err = Err("uh oh")
	Try.map2(Try.Ok(2), err, |a, b| a * b) == Err("uh oh")
}
map2! : Try(a, err), Try(b, err), (a, b => c) => Try(c, err)

Like Try.map2, but the combining function is effectful. It runs only when both arguments are Ok.

Try.map2!(user_try, album_try, |u, a| SQL.execute!("INSERT INTO plays (user, album) VALUES (?, ?)", [u.id, a.id]))
on_err : Try(ok, a), (a -> Try(ok, b)) -> Try(ok, b)

If the result is Err, runs a recovery function on the value it holds. That function returns a new result, so recovering can itself fail — with a different error type if you like. If the result is Ok, this has no effect. Use Try.map_err when you only want to transform the error without recovering from it.

expect {
	err : Try(I64, Str)
	err = Err("uh oh")
	err.on_err(|_| Ok(0)) == Ok(0)
}

expect {
	ok : Try(I64, Str)
	ok = Ok(7)
	ok.on_err(|_| Ok(0)) == Ok(7)
}
on_err! : Try(ok, a), (a => Try(ok, b)) => Try(ok, b)

Like Try.on_err, but the recovery function is effectful. It runs only when the result is an Err.

config_try.on_err!(|_| Http.get!("https://example.com/fallback-config"))
catch : Try(ok, err), (err -> a), (ok -> a) -> a

Collapses the result into a plain value by converting whichever variant it holds into a common type: err_transform runs on an Err, ok_transform on an Ok. Unlike Try.map_both, both functions return the same type, so the answer is a plain value rather than another result.

expect Try.Ok(12.I64).catch(|_| 0, |n| n * 2) == 24

expect {
	err : Try(I64, Str)
	err = Err("uh oh")
	err.catch(|_| 0, |n| n * 2) == 0
}
catch! : Try(ok, err), (err => a), (ok => a) => a

Like Try.catch, but the conversion functions are effectful. Only the effect matching the variant this result holds is run.

response.catch!(|e| Log.error!("request failed: ${e}"), |body| Log.info!("got ${body}"))
collapse : Try(a, a) -> a

Returns whichever value this result holds, for a result whose Ok and Err hold the same type. This is Try.catch with two identity functions.

expect Try.Ok(5.I64).collapse() == 5

expect Try.Err(7.I64).collapse() == 7
is_eq : Try(ok, err), Try(ok, err) -> Bool
    where [
        ok.is_eq : ok, ok -> Bool,
        err.is_eq : err, err -> Bool,
    ]

Returns Bool.True if the two Try values are the same variant (Ok or Err) and their contents are pairwise equal. Otherwise, returns Bool.False.

to_hash : Try(ok, err), Hasher -> Hasher
    where [
        ok.to_hash : ok, Hasher -> Hasher,
        err.to_hash : err, Hasher -> Hasher,
    ]

Feed a Try into a Hasher.