OCaml has built-in printing functions for several of the built-in
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
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
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
(), 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.
e1 does not have type
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