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.
We refer to functions with type 'a -> 'b Deferred.t as asynchronous
functions. We can think of them as 'a -> 'b functions that take a while
to complete. We informally say the function "completes" when the Deferred
returned by the function becomes determined.
val (>>=) : 'a Deferred.t ->
('a -> 'b Deferred.t) -> 'b Deferred.t
>>=
is used to chain asynchronous 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 asynchronous function g
on the output of
f
, and then run the asynchronous 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-asynchronous 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 asynchronous
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-asynchronous, we use >>|
. We then
pass the combined list of lines to the map_reduce
function
(using >>=
since map_reduce
is a asynchronous function), and
finally pass the results of map_reduce
to the (asynchronous)
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 asynchronous 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 asynchronous 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
.