Well I hope you’re intrigued now
I’m reading “OCaml from the very beginning”, I’m on the last chapter and I should reverse the contents of a file, to another file.
This is my entry point:
let rev_file (Valid_path p) = let ic = open_in p in let oc = open_out (p ^ ".rev") in do_rev ic oc ; close_in ic ; close_out oc ;;
I’m only concentrating on
do_rev from now on.
That was my iteration n°1, imperative style:
let do_rev ic oc = let out = ref  in try while true do let line = input_line ic in out := line :: !out done with | End_of_file -> let output = String.concat "\n" !out ^ "\n" in output_string oc output ;;
On iteration n°2, I wondered if I could make the code cleaner by making it more functional:
let do_rev ic oc = let rec build_lines acc = try build_lines (input_line ic :: acc) with | End_of_file -> acc in let rec put_lines lst = match lst with |  -> () | h :: t -> output_string oc (h ^ "\n") ; put_lines t in build_lines  |> put_lines ;;
At iteration n°3, I saw a pattern and could collapse
put_lines into a terser construct:
let do_rev ic oc = let rec build_lines acc = try build_lines (input_line ic :: acc) with | End_of_file -> acc in let output_line line = output_string oc (line ^ "\n") in let put_lines = List.iter output_line in build_lines  |> put_lines ;;
For the final version, I’d like to remove the exception that’s used as a control-flow mechanism. I wondered what I could do with
build_lines if I had a different API to begin with:
let input_line' ic = try Some (input_line ic) with | End_of_file -> None ;;
This allows me to “collapse”
new_lines in a similar fashion:
let what_is_it next = let rec loop next acc = match next () with | Some x -> loop next (x :: acc) | None -> acc in loop next  ;; let do_rev ic oc = let new_lines = what_is_it (fun () -> input_line' ic) in let output_line line = output_string oc (line ^ "\n") in let put_lines = List.iter output_line in new_lines |> put_lines ;;
However, I’m wondering what the function
what_is_it could be called? It’s similar, but different from all the functions I already know about.
Is there a commonly used function that does the same job? Even in an alternative standard lib? I wouldn’t want to re-invent the wheel.