(* binding - reminder about let and letrec *)
let foo x = x + 1 in
let bar x = foo (x - 1)
in bar 3110
let foo x = x + 1
and bar x = foo (x - 1) (* error - foo is unbound *)
in bar 3110
let rec foo x = bar (x - 1)
and bar x = x + 1
in foo 3110 (* functions foo and bar can refer to themselves and each other *)
let rec x = 1
and y = x + 1 (* error *)
in x + y
let square x = x *. x
(* form of function definitions we have been using, float * float -> float *)
let zig (x, y) = x +. 2. *. y
(* alternative form using pattern matching *)
let zig z = match z with (x, y) -> x +. 2. *. y
(* curried form float -> float -> float *)
let zigc x y = zig (x, y)
(* as an anonymous function *)
let zigc = fun x -> fun y -> zig (x, y)
let z = zigc (square 2.) 1.
(* partial evaluation: apply zigc to first argument only *)
let zp = zigc (square 2.)
let z = zp 1.
(* can also use labels to specify parameters *)
let zigcl ~x ~y = x +. 2. *. y
(* don't need labels if order of arguments is the same *)
let z = zigcl (square 2.) 1.
(* but can also do in opposite order with labels *)
let z = zigcl ~y:(square 2.) ~x:1.
(* partial eval with one arg, specify which with label *)
let zp = zigcl ~x:(square 2.)
let z = zp 1.
let zp = zigcl ~y:(square 2.)
let z = zp 1.
(* lists - sequences of arbitrary length, unlike tuples/records which are fixed length *)
[1; 2]
(* single type of element *)
[1; "a"] (* error - can't have heterogeneous lists *)
[] (* empty list *)
(* cons, ::, takes element and list and returns list with element at front *)
1 :: 2 :: [] = [1; 2]
1 :: 2 (* error, second arg not list *)
(* concat, @, takes two lists and concatenates, must copy first list so can be slow *)
[1; 2] @ [3; 4] = [1; 2; 3; 4]
(* pattern matching on lists *)
(* Returns the length of lst *)
let rec length (lst : 'a list) : int =
match lst with
| [] -> 0
| h :: t -> 1 + length t
let z = length ["a"; "b"; "c"]
(* return nth element of list -- note curried parameters *)
let rec nth (lst : 'a list) (n : int) : 'a =
match lst with
| h :: t -> if n = 0 then h else nth t (n - 1)
| [] -> raise Not_found
let z = nth ["a"; "b"; "c"] 2
(* partial evaluation *)
let select = nth ["a"; "b"; "c"]
let z = select 2