(* clear.ml *)
#use "topfind";;
#require "unix";;
let () =
for n = 0 to 100 do
print_endline "\x1b[H\x1b[2J";
Printf.printf "%d\n" n;
Unix.sleep 1
done
the C version behaves as expected, the OCaml version clears the screen but seems to fail at updating it. I wonder if this is a bug or an implementation detail of print_* functions.
This seems to be due to the buffering that is introduced by the OCaml implementation of printf. Adding %! to the end of the format string in the loop – to explicitly flush the buffer on each iteration – fixes the issue for me.
let () =
for n = 0 to 100 do
print_endline "\x1b[H\x1b[2J";
Printf.printf "%d\n%!" n;
Unix.sleep 1
done
Just for curiosity’s sake; is buffering applied also to the print_* functions? Or is it just a Printf impl. detail?
Because using print_int instead does still produce this unexpected behaviour.
can flushing be done without Printf (i.e. print_int)?
Providing you switch out the printf usage for the equivalent of print_int and print_endline, it should work as intended:
let () =
for n = 0 to 100 do
print_endline "\x1b[H\x1b[2J";
print_int n;
print_endline "";
Unix.sleep 1
done
This works because print_endlineperforms a flush. The channels provided by the standard library are buffered, and these buffers can be flushed with either Stdlib.flush or Stdlib.flush_all.
Just to add some background info that most probably know already …
C stdio output does use buffering, by default anyway, and to be specific printf() is buffered. It is however “line buffered” for TTY devices or for stderr - when a line feed is output, the buffer is then flushed. For other devices - pipes, disk files - not open on stderr, it’s block buffered, so the flush waits until the buffer fills, is explicitly flushed or the file is closed.