Printing
OCaml has built-in printing functions for several of the built-in
primitive types: print_char
, print_int
, print_string
, and
print_float
. There's also a print_endline
function, which is like
print_string
, but also outputs a newline.
Let's look at the type of a couple of those functions:
# print_endline;;
- : string -> unit = <fun>
# print_string;;
- : string -> unit = <fun>
They both take a string as input and return a value of type unit
,
which we haven't seen before. There is only one value of this type,
which is written ()
and is also pronounced "unit". So unit
is like
bool
, except there is one fewer value of type unit
than there is of
bool
. Unit is therefore used when you need to take an argument or
return a value, but there's no interesting value to pass or return. Unit
is often used when you're writing or using code that has side effects.
Printing is an example of a side effect: it changes the world and can't
be undone.
If you want to print one thing after another, you could sequence some print functions using nested let expressions:
let x = print_endline "THIS" in
let y = print_endline "IS" in
print_endline "3110"
But the boilerplate of all the let x = ... in
above is annoying to
have to write! We don't really care about giving names to the unit
values returned by those printing functions. So there's a special
syntax that can be used to chain together multiple functions who return
unit. The expression e1; e2
first evaluates e1
, which should
evaluate to ()
, then discards that value, and evaluates e2
. So we
could rewrite the above code as:
print_endline "THIS";
print_endline "IS";
print_endline "3110"
And that is far more idiomatic code.
If e1
does not have type unit
, then e1; e2
will give a warning, because
you are discarding useful values. If that is truly your intent, you can call
the built-in function ignore : 'a -> unit
to convert any value to ()
:
# 3; 5;;
Warning 10: this expression should have type unit.
- : int = 5
# ignore 3; 5;;
- : int = 5