Previous Contents Next

Input-Output

Input-output functions do calculate a value (often of type unit) but during their calculation they cause a modification of the state of the input-output peripherals: modification of the state of the keyboard buffer, outputting to the screen, writing in a file, or modification of a read pointer. The following two types are predefined: in_channel and out_channel for, respectively, input channels and output channels. When an end of file is met, the exception End_of_file is raised. Finally, the following three constants correspond to the standard channels for input, output, and error in Unix fashion: stdin, stdout, and stderr.

Channels

The input-output functions from the Objective CAML standard library manipulate communication channels: values of type in_channel or out_channel. Apart from the three standard predefined values, the creation of a channel uses one of the following functions:

# open_in;;
- : string -> in_channel = <fun>
# open_out;;
- : string -> out_channel = <fun>
open_in opens the file if it exists2, and otherwise raises the exception Sys_error. open_out creates the specified file if it does not exist or truncates it if it does.

# let ic = open_in "koala";;
val ic : in_channel = <abstr>
# let oc = open_out "koala";;
val oc : out_channel = <abstr>
The functions for closing channels are:

# close_in ;;
- : in_channel -> unit = <fun>
# close_out ;;
- : out_channel -> unit = <fun>


Reading and Writing

The most general functions for reading and writing are the following:

# input_line ;;
- : in_channel -> string = <fun>
# input ;;
- : in_channel -> string -> int -> int -> int = <fun>
# output ;;
- : out_channel -> string -> int -> int -> unit = <fun>


The following functions read from standard input or write to standard output:

# read_line ;;
- : unit -> string = <fun>
# print_string ;;
- : string -> unit = <fun>
# print_newline ;;
- : unit -> unit = <fun>


Other values of simple types can also be read directly or appended. These are the values of types which can be converted into lists of characters.

Local declarations and order of evaluation
We can simulate a sequence of printouts with expressions of the form let x = e1 in e2. Knowing that, in general, x is a local variable which can be used in e2, we know that e1 is evaluated first and then comes the turn of e2. If the two expressions are imperative functions whose results are () but which have side effects, then we have executed them in the right order. In particular, since we know the return value of e1---the constant () of type unit---we get a sequence of printouts by writing the sequence of nested declarations which pattern match on ().


# let () = print_string "and one," in
let () = print_string " and two," in
let () = print_string " and three" in
print_string " zero";;
and one, and two, and three zero- : unit = ()


Example: Higher/Lower

The following example concerns the game ``Higher/Lower'' which consists of choosing a number which the user must guess at. The program indicates at each turn whether the chosen number is smaller or bigger than the proposed number.


# let rec hilo n =
let () = print_string "type a number: " in
let i = read_int ()
in
if i = n then
let () = print_string "BRAVO" in
let () = print_newline ()
in print_newline ()
else
let () =
if i < n then
let () = print_string "Higher"
in print_newline ()
else
let () = print_string "Lower"
in print_newline ()
in hilo n ;;
val hilo : int -> unit = <fun>


Here is an example session:
# hilo 64;;
type a number: 88
Lower
type a number: 44
Higher
type a number: 64
BRAVO

- : unit = ()

Previous Contents Next