Caml is a general-purpose programming language, designed with program safety and reliability in mind. It is very expressive, yet easy to learn and use.
It is the first time I learn OCaml: http://caml.inria.fr/pub/docs/manual-ocaml/index.html (Part 1: the core language)
Programming:
1. List
define a list -> let l =["a "; "b";"c"];;
add an element to a list -> “life” ::” l”;;
define a function on list:
– match list with [] -> [] or [elt]
– define the core function: | head :: tail -> function body.
list.assoc returns the data associated with a given key in a list of (key, data) pairs, and raises the predefined exception Not_found when teh key does not appear in the list:
let name_of_binary_digit digit =
try
List.assoc digit [0, "zero"; 1, "one"]
with Not_found -> “not a binary digit”;;
2. Function
let deriv f dx = function x -> ( f ( x +. dx) -. f(x)) /.dx;;
let compose f g = function x -> f (g (x));;
apply function n to each element in a list:
List.map (function n -> n*2+1) [0;1;2;3], or
let rec map f l=
match l with
[] ->[]
| hd::tl -> f hd:: map f tl;;
3. Records
Define a record type:
type ratio = { num: int; denum: int};;
Define a function on record:
let add_ratio r1 r2 =
{num = r1.num * r2.denum + r2.num * r1.denum;
denum = r1.denum * r2.denum};;
Apply the function:
add_ratio {num=1; denum=3} {num=2; denum=5};;
4. The most common usage of variant types is to describe recursive data structures.
Define a binary tree:
type ‘a btree = Empty | Node of ‘a * ‘a btree * ‘a btree;;
Define a recursive function on a binary tree:
let rec member x btree =
match btree with
Empty -> false
| Node(y, left, right) ->
if x = y then true else
if x
5. For:
let add_vect v1 v2 =
let len = min (Array.length v1) (Array.length v2) in
let res = Array.create len 0.0 in
for i = 0 to len – 1 do
res.(i)
apply this function: add_vect [ | 1.0; 2.0 |] [| 2.0; 3.0|];;
6. The let binding is not an assignment, but introduces a new identifier with a new scope. However, the standard library provides references, which are mutable indirection cells, with operators ! to fetch the current contents of the refence and := to assign the contents.
let insertion_sort a =
for i = 1 to Array.length a – 1 do
let val_i = a.(i) in
let j = ref i in
while !j > 0 && val_i
7. Try … with
The with part is actually a regular pattern-matching on the exception value.
let temporarily_set_reference ref newval funct=
let oldval = !ref in
try
ref := newval;
let res = funct () in
ref := oldval;
res
with x ->
ref := oldval;
raise x;;
8. some examples I like:
Example1:
# let rec eval env exp =
match exp with
Const c -> c
| Var v ->
(try List.assoc v env with Not_found -> raise(Unbound_variable v))
| Sum(f, g) -> eval env f +. eval env g
| Diff(f, g) -> eval env f -. eval env g
| Prod(f, g) -> eval env f *. eval env g
| Quot(f, g) -> eval env f /. eval env g;;
# eval [("x", 1.0); ("y", 3.14)] (Prod(Sum(Var “x”, Const 2.0), Var “y”));;
Example2:
# let rec deriv exp dv =
match exp with
Const c -> Const 0.0
| Var v -> if v = dv then Const 1.0 else Const 0.0
| Sum(f, g) -> Sum(deriv f dv, deriv g dv)
| Diff(f, g) -> Diff(deriv f dv, deriv g dv)
| Prod(f, g) -> Sum(Prod(f, deriv g dv), Prod(deriv f dv, g))
| Quot(f, g) -> Quot(Diff(Prod(deriv f dv, g), Prod(f, deriv g dv)),
Prod(g, g));;
# deriv (Quot(Const 1.0, Var “x”)) “x”;;
- : expression =
Quot (Diff (Prod (Const 0., Var “x”), Prod (Const 1., Const 1.)),
Prod (Var “x”, Var “x”))