Promises Package¶
A Promise
represents a value that will be available at a later
time. Promise
s can either be fulfilled with a value or rejected. Any
number of function handlers can be added to the Promise
, to be
called when the Promise
is fulfilled or rejected. These handlers
themselves are also wrapped in Promise
s so that they can be chained
together in order for the fulfilled value of one Promise
to be used
to compute a value which will be used to fulfill the next Promise
in
the chain, or so that if the Promise
is rejected then the subsequent
reject functions will also be called. The input and output types of a
fulfill handler do not have to be the same, so a chain of fulfill
handlers can transform the original value into something new.
Fulfill and reject handlers can either be specified as classes that
implment the Fulfill
and Reject
interfaces, or as functions with
the same signatures as the apply
methods in Fulfill
and Reject
.
In the following code, the fulfillment of the Promise
causes the
execution of several fulfillment functions. The output is:
use "promises"
class PrintFulfill is Fulfill[String, String]
let _env: Env
let _msg: String
new create(env: Env, msg: String) =>
_env = env
_msg = msg
fun apply(s: String): String =>
_env.out.print(" + ".join([s; _msg].values()))
s
actor Main
new create(env: Env) =>
let promise = Promise[String]
promise.next[String](recover PrintFulfill(env, "foo") end)
promise.next[String](recover PrintFulfill(env, "bar") end)
promise.next[String](recover PrintFulfill(env, "baz") end)
promise("fulfilled")
In the following code, the fulfill functions are chained together so
that the fulfilled value of the first one is used to generate a value
which fulfills the second one, which in turn is used to compute a
value which fulfills the third one, which in turn is used to compute a
value which fulfills the fourth one. The output is the average length
of the words passed on the command line or 0
if there are no command
line arguments.
use "promises"
primitive Computation
fun tag string_to_strings(s: String): Array[String] val =>
recover s.split() end
fun tag strings_to_sizes(sa: Array[String] val): Array[USize] val =>
recover
let len = Array[USize]
for s in sa.values() do
len.push(s.size())
end
len
end
fun tag sizes_to_avg(sza: Array[USize] val): USize =>
var acc = USize(0)
for sz in sza.values() do
acc = acc + sz
end
acc / sza.size()
fun tag output(env: Env, sz: USize): None =>
env.out.print(sz.string())
actor Main
new create(env: Env) =>
let promise = Promise[String]
promise.next[Array[String] val](recover Computation~string_to_strings() end)
.next[Array[USize] val](recover Computation~strings_to_sizes() end)
.next[USize](recover Computation~sizes_to_avg() end)
.next[None](recover Computation~output(env) end)
promise(" ".join(env.args.slice(1).values()))