Author: Christian.Queinnec@lip6.fr

## 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>

- input_line`` ic: reads from input channel `ic` all the characters up to the first carriage return or end of file, and returns them in the form of a list of characters (excluding the carriage return).
- input`` ic`` s`` p`` l: attempts to read `l` characters from an input channel `ic` and stores them in the list `s` starting from the `p`th character. The number of characters actually read is returned.
- output`` oc`` s`` p`` l: writes on an output channel `oc` part of the list `s`, starting at the `p`-th character, with length `l`.

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 = ()