I had a trivial little Lwt program like this:
let read_name =
let%lwt name = Lwt_io.(read_line stdin) in
Lwt.return (Some name)
let timeout =
let%lwt () = Lwt_unix.sleep 3.0 in
Lwt.return None
let () =
print_endline "Enter your name (but don't take too long)";
let first_resolved = Lwt_main.run (Lwt.pick [ read_name; timeout ])
in
match first_resolved with
| Some name -> Printf.printf "Hello %s\n" name
| None -> print_endline "Too slow!"
It’s working just fine and neither read_name
nor timeout
need to be actual functions because, well, they are promises so everything gets deferred.
Then I add another block, rewriting read_name
without the specialised let.
let _read_name =
let name_promise = Lwt_io.(read_line stdin) in
Lwt.bind name_promise (fun name -> Lwt.return (Some name))
I make some other tweaks, add some comments and all of a sudden, now my program consumes an extra newline: “Fred” gives an empty string and “Fred” is what you need to type to get “Hello Fred”.
I will skip over the confusion and head-scratching (of course I didn’t re-run the program until the next day at which point I wasn’t sure if it had worked properly in the first place).
My mistake? I inserted that second block of code before the read_name
I was actually using. And since they weren’t actually functions but just values both were being evaluated. And _read_name
also has read_line stdin
so was consuming my first line of data.
Use actual functions and Lwt.pick [ read_name (); timeout () ]
and all is good.
Hopefully if someone else makes the same mistake this post will have enough keywords to make it searchable.