3

I'm trying to write a terminal application with Lwt. Basically as longs as my app is running, I need to watch the terminal for input with Lwt_io.read_line.

Is there a better way than the following (pseudocode) to achieve some kind of loop while my program is running?

while true do
  let _ = ignore (Lwt_main.run my_application)
done

I'm not sure if this is the right way. Every time all the threads from my_application have finished, the Lwt_main.run gets invoked again & again & again...

Are there other or better ways to handle this with Lwt?

Seneca
  • 2,392
  • 2
  • 18
  • 33

1 Answers1

4

You would typically write your main loop as a recursive function, which evaluates to a thread, then pass that thread once to Lwt_main.run. Here is a small example:

let () =
  let rec echo_loop () =
    let%lwt line = Lwt_io.(read_line stdin) in
    if line = "exit" then
      Lwt.return_unit
    else
      let%lwt () = Lwt_io.(write_line stdout line) in
      echo_loop ()
  in

  Lwt_main.run (echo_loop ())

This can be compiled and run with:

ocamlfind opt -linkpkg -package lwt.unix -package lwt.ppx code.ml && ./a.out

In rough terms, this is what happens in the above code:

  1. echo_loop () is applied in the argument of Lwt_main.run. This immediately begins evaluating Lwt_io.(read_line stdin), but the rest of the code (starting with the if expression) is put into a closure to be run once the read_line completes. echo_loop () then evaluates to this combination of an ongoing read_line operation followed by the closure.
  2. Lwt_main.run forces your process to wait until all that completes. However, once the read_line completes, if the line is not exit, the closure triggers a write_line operation, followed by another closure, which calls echo_loop () recursively, which starts another read_line, and this can go on indefinitely.
antron
  • 3,749
  • 2
  • 17
  • 23