Input-Output (original) (raw)
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 exceptionSys_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
- input
- 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 = e 1 in e 2. Knowing that, in general, x is a local variable which can be used in e 2, we know that e 1 is evaluated first and then comes the turn of_e_ 2. 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 e _1_---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 = ()