Ppx syntax extension for Lwt
Ppx extensions
This Ppx extension adds various syntactic shortcut for lwt programming. It needs OCaml >= 4.02 and ppx_tools.
To use it, simply use the ocamlfind package lwt.ppx
.
This extension adds the following syntax:
let%lwt ch = get_char stdin in
code
is the same as bind (get_char stdin) (fun ch -> code)
.
Moreover, it supports parallel binding:
let%lwt x = do_something1 ()
and y = do_something2 in
code
will run do_something1 ()
and do_something2 ()
, then bind their results to x
and y
. It is the same as:
let t1 = do_something1
and t2 = do_something2 in
bind t1 (fun x -> bind t2 (fun y -> code))
try%lwt
<expr>
with
<branches>
For example:
try%lwt
f x
with
| Failure msg ->
prerr_endline msg;
return ()
is expanded to:
catch (fun () -> f x)
(function
| Failure msg ->
prerr_endline msg;
return ()
| exn ->
Lwt.fail exn)
Note that the exn -> Lwt.fail exn
branch is automatically added when needed.
(<expr>) [%finally <expr>]
You can use [%lwt.finally ...]
instead of [%finally ...]
.
assert%lwt <expr>
for%lwt i = <expr> to <expr> do
<expr>
done
and:
for%lwt i = <expr> downto <expr> do
<expr>
done
while%lwt <expr> do
<expr>
done
match%lwt <expr> with
| <patt_1> -> <expr_1>
...
| <patt_n> -> <expr_n>
Exception cases are also supported:
match%lwt <expr> with
| exception <exn> -> <expr_1>
| <patt_2> -> <expr_2>
...
| <patt_n> -> <expr_n>
if%lwt <expr> then
<expr_1>
else
<expr_2>
and
if%lwt <expr> then <expr_1>
For all other expression, the construct
[%lwt <expr>]
is expanded to:
Lwt.catch (fun () -> <expr>) Lwt.fail
It allows to encode the old raise_lwt <e>
as [%lwt raise <e>]
, and offers a convenient way to interact with non-Lwt code.
Debug
By default, the debug mode is enabled. This means that the backtrace
versions of the bind
, finalize
and catch
functions are used, enabling proper backtraces for the Lwt exceptions.
The debug mode can be disabled with the option -no-debug
:
$ ocamlfind ocamlc -package lwt.ppx \
-ppxopt lwt.ppx,-no-debug -linkpkg -o foo foo.ml
Sequence
With OCaml 4.04.0 and on a convenient syntax is available for sequencing Lwt operations using ;%lwt
. This allows free mixing of standard ;
sequencing and ;%lwt
sequencing without extra parentheses:
let i = ref 0 in
write stdout "Hello, ";%lwt
incr i;
write stdout "world!"
It is also possible to sequence Lwt operations with the >>
operator:
write stdout "Hello, " >> write stdout "world!"
By default, each operation must return unit Lwt.t
. This constraint can be lifted with the option -no-strict-sequence
. The operator can be disabled with the option -no-sequence
.
If you are mixing `>>` and `;`, you need to use parentheses or `begin`/`end` to get the result you expect:
write stdout "Hello, " >> (ignore (); write stdout "world!")
Note that unlike >>=
, >>
is not an OCaml value. it is a piece of syntax added by the ppx rewriter - i.e., you cannot refer to (>>)
.
Logging
The logging syntax extension is enabled with -log
. It will replace expressions of the form:
Lwt_log.info_f ~section "x = %d" x
by
if Lwt_log.Section.level section <= Lwt_log.Info then
Lwt_log.info_f ~section "x = %d" x
else
return ()
Notes:
- The application must be complete. For example:
Log.info "%d"
will make compilation fail.
- Debug messages are removed if the option
-no-debug
is passed.