ocamlocaml-lwt

Ocaml lwt never ending loop


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?


Solution

  • 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.