eval

steps.result.Result.eval
object eval

Operations that are valid under a Result.apply scope.

Attributes

See also
Graph
Supertypes
class Object
trait Matchable
class Any
Self type
eval.type

Members list

Grouped members

eval

inline def ok: T

Unwraps the result, returning the value under Ok. Short-circuits the current body under Result.apply with the given error if the result is an Err.

Unwraps the result, returning the value under Ok. Short-circuits the current body under Result.apply with the given error if the result is an Err.

val ok = Ok(1)
val err = Err("fail!")

val compute = Result:
 ok.ok      // ok, unwraps and gives 1
   + err.ok // error, immediately sets compute to Err("fail")
   + f()   // not evaluated

Attributes

See also

apply and raise.

inline def raise[E, E1](err: E)(using label: Label[Err[E1]])(using conversion: Conversion[E, E1]): Nothing

Short-circuits the current body under Result.apply with the given error.

Short-circuits the current body under Result.apply with the given error.

Attributes

Value members

Concrete methods

inline def apply[T, E](inline body: (Label[Result[T, E]]) ?=> T): Result[T, E]

Similar to Result.apply.

Similar to Result.apply.

Attributes

transparent inline def break[T, E](inline r: Result[T, E]): Result[T, E]

A shorthand to call boundary.break with a Result label. This is useful in case an early return is needed, or a tail recursion call (returning a Result) is called.

A shorthand to call boundary.break with a Result label. This is useful in case an early return is needed, or a tail recursion call (returning a Result) is called.

For example, tryFoldLeft on Seq can be implemented like below:

extension[T] (seq: Seq[T])
 @scala.annotation.tailrec
 def tryFoldLeft[U, E](init: U)(f: (U, T) => Result[U, E]): Result[U, E] =
   Result:
     seq match
       case Seq() => init
       case Seq(h, t*) =>
         // t.tryFoldLeft(f(init, h).ok)(f).ok        // error: not a tail call (.ok applied at the end)
         eval.break(t.tryFoldLeft(f(init, h).ok)(f)) // ok

Note that however, in most cases, it is simpler to capture the Result.apply from outside of the tailrec loop, as this minimizes the amount of boxing/unboxing Result needed on every step:

extension[T] (seq: Seq[T])
 def tryFoldLeft[U, E](init: U)(f: (U, T) => Result[U, E]): Result[U, E] =
   Result:
     @scala.annotation.tailrec
     def loop(current: U, seq: Seq[T]): U = // note the return type
       seq match
         case Seq() => current
         case Seq(h, t*) => loop(f(current, h).ok, t)
     loop(init, seq)

Of course, one could also simply rewrite it in terms of .foldLeft:

extension[T] (it: IterableOnce[T])
 def tryFoldLeft[U, E](init: U)(f: (U, T) => Result[U, E]): Result[U, E] =
   Result:
     it.iterator.foldLeft(init)(f(_, _).ok)

Attributes

Returns

Always returns Nothing, but the return type is set so that Scala does not infer T and E contravariantly.