It is a great pleasure to announce the release of the first alpha release of Lwt 6. This major version bump brings two major changes to Lwt:
Using Lwt in direct-style! (Big thanks to @c-cube !!)
Using multiple Lwt schedulers running in separate domains!
Direct-style
This contribution from @c-cube is available in alpha00. It comes in the form of an lwt_direct package which provide an Lwt_direct module which provide two core functions:
val run : (unit -> 'a) -> 'a Lwt.t
val await : 'a Lwt.t -> 'a
and allows you to write code such as
run (fun () ->
let continue = ref true in
while !continue do
match await @@ Lwt_io.read_line ic with
| line -> await @@ Lwt_io.write_line oc line
| exception End_of_file -> continue := false
done)
There are a few more functions. All of which is documented in lwt_direct.mli.
Multi-scheduler
This addition is not available in alpha00 but should be added to alpha01 soon. It allows to call Lwt_main.run in different domains and benefit from actual parallelism. (Sneak peek in this pull request)
Installation
lwt.6.0.0~alpha00 and lwt_direct.6.0.0~alpha00 will soon be released on opam (PR on opam-repo. Iâll publish some more alphas as the work progresses, and announce the releases on this thread.
You can also pin the packages to the lwt-6 branch to get everything a little bit earlier:
No, itâs !continue, to read the reference . There are multiple ways to write this loop, but here it emphasizes the (new) possibility of writing direct style code that runs on Lwtâs scheduler and can wait on any Lwt.t promise.
Dâoh! The perils of working in different languages all the time. I still canât read it as anything other than âwhile notâ even now - the habit is too deeply ingrained. Itâs switching between semicolon-terminated and not that mostly gets me for the first hour or two.
Question: why in a separate Lwt_direct module? Why not in the main Lwt module itself? Is it because of the name run? Could we use Lwt.defer and Lwt.now instead?
In the current state of things, lwt_direct requires OCaml 5 while lwt doesnât. I think otherwise it could make sense for Lwt_direct to live in the lwt library, just maybe not in the Lwt module itself â after all itâs not about promises as much as the moral equivalent of microtasks.
Itâs an add-on to lwt offering a different way of thinking, while keeping full compatibility with the ecosystem. A separate module seems reasonable to me
Iâm not sure why you would pick names like defer and now. defer sounds like a resource handling function, and now like a clock function?
now is just a contrast to âdeferâ, as in âget the value laterâ vs âget the value nowâ. âDeferâ terminology is also used by Jane Street Asyncâtheir promise type is 'a Deferred.t.
Maybe async and await would actually be better choices, but there is already Lwt.async so it might be confusing.
I think itâs a good question, since @raphael-proust has in the works a multicore PR (one Lwt event loop per domain). Even then I think a separate module would be good, inside the lwt library.
Thanks for explaining defer and now. I think await is non-negotiable, itâs almost universal at this point. run is a bit generic and I could imagine there being better names!
May be worth mentioning, the Lwt module is available and very useful in the js-of-ocaml world where effects-compilation is even younger (even kinda experimental?).
Yes, Lwt_direct.await promise will raise the exception e if promise failed with e. It all works normally, try ⌠with, match ⌠with exception âŚ, awaiting inside List.map, etc. Effects are awesome!