Lwt now has let* and let+ syntax, which can be used like this:
open Lwt.Syntax
let () =
let request =
let* addresses = Lwt_unix.getaddrinfo "google.com" "80" [] in
let google = Lwt_unix.((List.hd addresses).ai_addr) in
Lwt_io.(with_connection google (fun (incoming, outgoing) ->
let* () = write outgoing "GET / HTTP/1.1\r\n" in
let* () = write outgoing "Connection: close\r\n\r\n" in
let* response = read incoming in
Lwt.return (Some response)))
in
let timeout =
let* () = Lwt_unix.sleep 5. in
Lwt.return None
in
match Lwt_main.run (Lwt.pick [request; timeout]) with
| Some response -> print_string response
| None -> prerr_endline "Request timed out"; exit 1
This is now released in Lwt 5.3.0. Thanks to Rahul Kumar for adding let*, and @CraigFe for adding let+!
The docs generation is blocked on an Ocsigen “internal” package wikidoc, which has not been updated to support 4.08. So, effectively, let* is exactly what is preventing docs generation for the time being. I’ll post the docs as soon as that is fixed.
ppx_lwt is probably still the recommended way, because of better backtraces, and things like try%lwt. let* is nice for people that don’t want to use the PPX. They can still benefit from a monadic syntax.
about 2, I’ve think I’ve read that already some place. Are the things like try* on the roadmap for ocaml? Or are those things that we probably won’t see?
I presume there is no reason why you should not use let* in place of let%lwt if you are using ocaml >= 4.08, even if you are using ppx_lwt? After all, (let*) is presumably just an alias for Lwt.bind.
The let+ (mapping) operator is an interesting one. Is there a ppx_lwt equivalent for that? I don’t think I have ever come across a use for it if there is.
let%lwt should produce better backtraces, because only the PPX inserts a function at the call site that uses %reraise to extend the backtrace of an exception in the callback of the bind. This is what adds the location of the call site to the backtrace. The PPX actually uses backtrace_bind mentioned by @hcarty — that’s an internal version of bind with an extra callback argument, meant for that generated backtrace-extending function.
let* bypasses this completely and expands to ordinary bind. So, if the callback of bind ends up being called asynchronously (later), a backtrace generated by an exception raised at that point will lack the location of the call site, and will show only the backtrace to where the Lwt main loop was awakened, leading to the callback call. It won’t show where the bind actually happened.
Lwt really ought to have something better for this, but we never got around to it.
There are indeed no equivalents to let+ and Lwt_result.(let*) in the PPX.
I use let ( let*) = Lwt_result.bind in... quite frequently! It’s very useful in that context, with the caveats @antron mentioned relative to using let%lwt.