9.3 Delayed Evaluation
A promise encapsulates an expression to be evaluated on
demand via force. After a promise has been forced,
every later force of the promise produces the same result.
This module provides this functionality, and extends it to additional
kinds of promises with various evaluation strategies.
Returns #t if v is a promise, #f
otherwise.
Creates a promise that, when
forced, evaluates the
bodys to produce its value. The result is then cached, so
further uses of
force produce the cached value immediately.
This includes multiple values and exceptions.
Like
delay, if the last
body produces a promise when
forced, then this promise is
forced too to obtain a value.
In other words, this form creates a composable promise, where the
computation of its body is “attached” to the computation of the
following promise and a single
force iterates through the
whole chain, tail-calling each step.
Note that the last body of this form must produce a single
value – but this value can itself be a delay promise that
returns multiple values.
This form useful for implementing lazy libraries and languages, where
tail-calls can be wrapped in a promise.
If
v is a promise, then the promise is forced to obtain a
value. If the promise has not been forced before, then the result is
recorded in the promise so that future
forces on the promise
produce the same value (or values). If forcing the promise raises an
exception, then the exception is similarly recorded so that forcing
the promise will raise the same exception every time.
If v is forced again before the original call to
force returns, then the exn:fail exception is raised.
Additional kinds of promises are also forced via force. See
below for further details.
If v is not a promise, then it is returned as the result.
Returns #t if promise has been forced.
Returns #t if promise is currently being forced.
(Note that a promise can be either running or forced but not both.)
9.3.1 Additional Promise Kinds
Creates a “call by name” promise, that is similar to
delay-promises, except that the resulting value is not
cached. It is essentially a thunk, wrapped in a way that
force recognizes. Note that if a
delay/name promise
forces itself, no exception is raised.
Note that this promise is never considered “running” or “forced”
in the sense of promise-running? and
promise-forced?.
Conventional promises are not useful when multiple threads attempt to
force them: when a promise is running, any additional threads that
force it will get an exception.
delay/sync is
useful for such cases: if a second thread attempts to
force
such a promise, it will get blocked until the computation is done and
an answer is available. If
force is used with the promise as
it is forced from the same thread, an exception is raised.
In addition, these promises can be used with sync, which
blocks until it has been forced. Note that using sync this
way is passive in the sense that it does not trigger evaluation of the
promise.
This kind of promise begins the computation immediately, but this
happens on a separate thread. When the computation is done, the result
is cached as usual. Note that exceptions are caught as usual, and will
only be raised when
forced. If such a promise is
forced before a value is ready, the calling thread will be
blocked until the computation terminates. These promises can also be
used with
sync.
Similar to
delay/thread, but the computation thread gets to
work only when the process is otherwise idle, as determined by
system-idle-evt, and the work is done in small runtime
fragements, making it overall not raise total CPU use or hurt
responsiveness. If the promise is
forced before the
computation is done, it will run the rest of the computation immediately
without slicing the runtime. Using
sync on these promises
blocks as is the case with
delay/sync, and this happens in a
passive way too, so the computation continues to work in low-priority.