Creates a new Eval
by applying a function to the successful
result of the source, and returns a new instance equivalent to
the result of the function.
const rndInt = Eval.of(() => {
const nr = Math.random() * 1000000
return nr & nr
})
const evenInt = () =>
rndInt.flatMap(int => {
if (i % 2 == 0)
return Eval.now(i)
else // Retry until we have an even number!
return evenInt()
})
Triggers the evaluation of the source, executing the given function for the generated element.
The application of this function has strict behavior, as the coeval is immediately executed.
Returns a new Eval
that upon evaluation will execute the given
function for the generated element, transforming the source into
an Eval<void>
.
Similar in spirit with normal .forEach, but lazy, as obviously nothing gets executed at this point.
Evaluates the source Eval
and returns the result.
const ref = Eval.always(() => 100 * 2)
ref.get() // 200
Returns a new Eval
that applies the mapping function to the
successful result emitted by the source.
Eval.now(111).map(_ => _ * 2).get() // 222
Memoizes (caches) the result of the source on the first
evaluation and reuses it on subsequent invocations of get()
.
The resulting Eval
will be idempotent, meaning that
evaluating it multiple times will have the same effect
as evaluating it once.
Promote a thunk
function to an Eval
, catching exceptions in
the process.
Note that since Eval
is not memoized by global, this will
recompute the value each time the Eval
is executed.
Promote a thunk
function generating Eval
results to an Eval
of the same type.
Alias for Eval.suspend.
Maps 2 Eval
values by the mapping function, returning a new
Eval
reference that completes with the result of mapping that
function to the successful values of the futures, or in failure in
case either of them fails.
const fa1 = Eval.of(() => 1)
const fa2 = Eval.of(() => 2)
// Yields Success(3)
Eval.map2(fa1, fa2, (a, b) => a + b)
This operation is the Applicative.map2
.
Maps 3 Eval
values by the mapping function, returning a new
Eval
reference that completes with the result of mapping that
function to the successful values of the futures, or in failure in
case either of them fails.
const fa1 = Eval.of(() => 1)
const fa2 = Eval.of(() => 2)
const fa3 = Eval.of(() => 3)
// Yields Success(6)
Eval.map3(fa1, fa2, fa3, (a, b, c) => a + b + c)
Maps 4 Eval
values by the mapping function, returning a new
Eval
reference that completes with the result of mapping that
function to the successful values of the futures, or in failure in
case either of them fails.
const fa1 = Eval.of(() => 1)
const fa2 = Eval.of(() => 2)
const fa3 = Eval.of(() => 3)
const fa4 = Eval.of(() => 4)
// Yields Success(10)
Eval.map4(fa1, fa2, fa3, fa4, (a, b, c, d) => a + b + c + d)
Maps 5 Eval
values by the mapping function, returning a new
Eval
reference that completes with the result of mapping that
function to the successful values of the futures, or in failure in
case either of them fails.
const fa1 = Eval.of(() => 1)
const fa2 = Eval.of(() => 2)
const fa3 = Eval.of(() => 3)
const fa4 = Eval.of(() => 4)
const fa5 = Eval.of(() => 5)
// Yields Success(15)
Eval.map5(fa1, fa2, fa3, fa4, fa5,
(a, b, c, d, e) => a + b + c + d + e
)
Maps 6 Eval
values by the mapping function, returning a new
Eval
reference that completes with the result of mapping that
function to the successful values of the futures, or in failure in
case either of them fails.
const fa1 = Eval.of(() => 1)
const fa2 = Eval.of(() => 2)
const fa3 = Eval.of(() => 3)
const fa4 = Eval.of(() => 4)
const fa5 = Eval.of(() => 5)
const fa6 = Eval.of(() => 6)
// Yields Success(21)
Eval.map6(
fa1, fa2, fa3, fa4, fa5, fa6,
(a, b, c, d, e, f) => a + b + c + d + e + f
)
Returns an Eval
that on execution is always successful,
emitting the given strict value.
Alias for Eval.always.
Promote a thunk
function to a Coeval
that is memoized on the
first evaluation, the result being then available on subsequent
evaluations.
Note this is equivalent with:
Eval.always(thunk).memoize()
Transforms a list of Eval
values into an Eval
of a list.
Sample:
const io1 = Eval.of(() => 1)
const io2 = Eval.of(() => 2)
const io3 = Eval.of(() => 3)
// Yields [1, 2, 3]
const all: Eval<number[]> = Eval.sequence([f1, f2, f3])
Keeps calling f
until a Right(b)
is returned.
Based on Phil Freeman's Stack Safety for Free.
Described in FlatMap.tailRecM
.
Shorthand for now(undefined as void)
, always returning
the same reference as optimization.
Generated using TypeDoc
Eval is a monad which controls evaluation.
This type wraps a value (or an expression that produces a value) and can produce it on command via the get() method.
There are three basic evaluation strategies:
Eval supports stack-safe lazy computation via the .map and .flatMap methods, which use an internal trampoline to avoid stack overflows. Computation done within
map
andflatMap
is always done lazily, even when applied to anEval.now
instance.Use
map
andflatMap
to chain computation, and useget()
to get the result when needed. It is also not good style to createEval
instances whose computation involves callingget()
on anotherEval
instance -- this can defeat the trampolining and lead to stack overflows.const rndInt = Eval.of(() => { const nr = Math.random() * 1000000 return nr & nr }) const evenInt = () => rndInt.flatMap(int => { if (i % 2 == 0) return Eval.now(i) else // Retry until we have an even number! return evenInt() }) const cached = evenInt().memoize() // Nothing happens until now, this triggers the // actual evaluation: const n: number = cached.get()
Versus IO
For dealing with lazy evaluation, the other alternative is the IO data type.
Differences between
Eval
andIO
:IO
is capable of describing asynchronous computations as wellIO
is capable of error handling (it implementsMonadError
), whereasEval
does not provide error handling capabilities, being meant to be used for pure expressions (it implementsComonad
, which is incompatible withMonadError
)So if you need error handling capabilities (i.e.
MonadError<Throwable, ?>
), or if you need to describe asynchronous processes, then IO is for you.Eval
is a simpler data type with the sole purpose of controlling the evaluation of expressions (i.e. strict versus lazy).Credits
This type is inspired by
cats.Eval
from Typelevel Cats and bymonix.eval.Coeval
from Monix.