Range Over Channels in OCaml

Our example demonstrates how to iterate over values received from a channel in OCaml. While OCaml doesn’t have built-in channels like Go, we can simulate this behavior using the Event module from the Lwt library, which provides lightweight cooperative threads.

open Lwt
open Lwt_stream

let main () =
  (* We'll iterate over 2 values in the `queue` stream. *)
  let (stream, push) = Lwt_stream.create () in
  push (Some "one");
  push (Some "two");
  push None; (* This is equivalent to closing the channel *)

  (* This `Lwt_stream.iter` iterates over each element as it's
     received from `stream`. Because we pushed `None` to the stream above,
     the iteration terminates after receiving the 2 elements. *)
  Lwt_stream.iter (fun elem ->
    Lwt_io.printf "%s\n" elem
  ) stream

let () =
  Lwt_main.run (main ())

To run this program:

$ ocamlbuild -pkg lwt.unix main.native
$ ./main.native
one
two

This example shows how to create a stream, push values to it, and then iterate over those values. The None value pushed at the end acts similarly to closing a channel in Go, signaling the end of the stream.

In OCaml, we use the Lwt_stream module to create a stream that can be pushed to and read from asynchronously. The Lwt_stream.iter function allows us to process each element in the stream as it becomes available.

This example also demonstrates that it’s possible to signal the end of a non-empty stream but still have the remaining values be received and processed.