Now the semicolon operator, also known as the sequence operator, becomes more useful.
e1; e2e1 to a value v1e1 can have side effects)e2 to a value v2v2e1 : unite2 : te1; e2 : tThe semicolon is almost just syntactic sugar
e1; e2
(* is almost the same as *)
let () = e1 in e2
Except... it's not true that e1 : unit
e1's valueignore : 'a -> unit.let print_and_add x y = print_int (x + y); print_newline (); x + y;;
val print_and_add : int -> int -> int = <fun>
Here, our function prints adds integers, and prints and returns the result.
print_and_add 0 1;;
1
- : int = 1
print_and_add 1 2;;
3
- : int = 3
This works because print_int and print_newline both return unit
print_int;;
print_newline;;
- : int -> unit = <fun>
- : unit -> unit = <fun>
But what if we wanted to chain functions that don't return units?
print_and_add 0 1; print_and_add 1 2;;
File "[5]", line 1, characters 0-17:
1 | print_and_add 0 1; print_and_add 1 2;;
^^^^^^^^^^^^^^^^^
Warning 10: this expression should have type unit.
File "[5]", line 1, characters 0-17:
1 | print_and_add 0 1; print_and_add 1 2;;
^^^^^^^^^^^^^^^^^
Warning 10: this expression should have type unit.
- : int = 3
1 3
We get a warning! Let's use the ignore function to fix this
ignore @@ print_and_add 0 1; print_and_add 1 2;;
1 3
- : int = 3
That's better!