module Std:sig
..end
Async
. Async programs typically only
open Async.Std
, the modules within Async.Std
are typically referred to
explicitly.module Deferred:sig
..end
'a Deferred.t
is the most important type in the Async
library. An
'a Deferred.t
represents a value that will become determined
when an asynchronous computation completes.
A deferred can be "undetermined" or "determined". A deferred that is undetermined may at some point become determined with value v, and will henceforth always be determined with value v.
Any Async function that needs to wait for something to happen (i.e.
"block") will return a Deferred.t
. The function itself will return
immediately, allowing the calling program to continue to do other tasks.
Thus blocking functions should have the type 'a -> 'b Deferred.t
.
val (>>=) : 'a Deferred.t ->
('a -> 'b Deferred.t) -> 'b Deferred.t
>>=
is used to chain blocking functions together. x >>= g
will cause
g
to be run after x
is determined, with the value of x
as input. The
deferred returned by (>>=)
will become determined when g
completes.
There are two common stylistic idioms used when using >>=
. The first is
that many functions can be joined together with >>=
without parentheses.
For example, if one wants to wait for x
to be determined, and then run
f
on the result, and then run the blocking function g
on the output of
f
, and then run the blocking function h
on the result of f
, one would
write the following:
x >>= f >>= g >>= h
When splitting these invocations on multiple lines, one typically writes
x
>>= f
>>= g
>>= h
The second idiom is that anonymous function definitions are typically written inline and without parentheses. For example, in the above sequence, if we wanted to print the value that is passed from f to g, we would write:
x >>= f >>= fun y ->
print_endline y;
g y >>= h
This is the same as
x >>= (f >>= (fun y -> print_endline y; (g y >>= h)))
but the way it is written looks more like imperative code: first run f
on
x
and call the result y
. Then print y
. Then run g
on y
and pass
the result to h.
It is helpful to think of the pattern
f x >>= fun y ->
as being analogous to
let y = f x in
This is why (>>=)
is also called "bind".val (>>|) : 'a Deferred.t -> ('a -> 'b) -> 'b Deferred.t
>>|
is similar to >>=
, but it is used for non-blocking functions. It
can be mixed to chains of functions joined by >>=
. For example, the
provided function WordCount.App.Make.main
is implemented as follows:
Deferred.List.map Reader.file_lines filename
>>| List.flatten
>>= map_reduce
>>= output
filenames is a list of file names: ["foo.txt"; "bar.txt"]
.
Deferred.List.map
is like List.map except that it works with blocking
functions like Reader.file_lines
.
The output of this line is a list containing a list of lines of "foo.txt"
and a list of lines of "bar.txt"
. We want to combine these into a single
list, so we pass them through the List.flatten
function.
Since List.flatten
is non-blocking, we use >>|
. We then
pass the combined list of lines to the map_reduce
function
(using >>=
since map_reduce
is a blocking function), and
finally pass the results of map_reduce
to the (blocking)
output
function.
Be aware that >>|
does not play as nicely with anonymous functions as
>>=
does. The following code does not work:
f x >>| fun y ->
print_endline y;
g y >>= h
A good test of your understanding of the >>=
and >>|
syntax would be to
explain why.val return : 'a -> 'a Deferred.t
return
is used to create a Deferred.t
that is immediately determined
with the provided value. It is often used to designate the return value of
a function implemented using a chain of >>=
expressions. For example:
let run_fgh x =
f x >>= fun y ->
g y >>= fun z ->
h z >>= fun _ ->
return (y,z)
will first run f on x; when that completes it will run g, and then h. The
result of the deferred created by run_fgh
will be the pair (y,z)
.Deferred.t
sval don't_wait_for : unit Deferred.t -> unit
val never : unit -> 'a Deferred.t
Deferred.both
, Deferred.any
and Deferred.all
.module Ivar:sig
..end
ref
s.
module Pipe:sig
..end
Deferred.List
contains blocking versions of many familiar List
module functions.Core.Std.sec
to create Core.Std.Time.Span.t
s.
It takes in a float
t
and produces a Time.Span.t
representing t
seconds.val after : Core.Std.Time.Span.t -> unit Deferred.t
val with_timeout : Core.Std.Time.Span.t ->
'a Deferred.t -> [ `Result of 'a | `Timeout ] Deferred.t
with_timeout t x
will become determined with `Result v
if x
becomes
determined with v
within the timespan t
. Otherwise, the value will be
`Timeout
.val every : ?start:unit Deferred.t ->
?stop:unit Deferred.t ->
Core.Std.Time.Span.t -> (unit -> unit) -> unit
every t f
schedules f
to be executed every t
seconds. If the
arguments ?start
or ?finish
are supplied, f
will not be scheduled
before start
becomes determined or after finish
does.val printf : ('a, unit, string, unit) format4 -> 'a
Printf.printf
,
which is very useful for debugging.module Reader:sig
..end
Pipe.Reader
) is for doing
network and file input.
module Writer:sig
..end
Pipe.Writer
) is for doing
network and file output.
module Socket:sig
..end
Tcp
module.
module Tcp:sig
..end
val try_with : (unit -> 'a Deferred.t) ->
('a, exn) Core.Std.Result.t Deferred.t
try_with f
runs the blocking function f
, and returns Core.Std.Ok x
if
f ()
returns x
. If f ()
raises the exception e
, then try_with f
returns Core.Std.Error e
.