oCamlCase

Bindings

let binding
let x = 42
let name = "Alice"
let pi : float = 3.14159
(* immutable by default *)
let … in (local scope)
let result =
  let a = 10 in
  let b = 20 in
  a + b    (* 30 *)
mutable ref
let n = ref 0
n := !n + 1
Printf.printf "%d\n" !n  (* 1 *)
destructuring
let (a, b)       = (1, 2)
let { name; age } = person
let x :: rest    = [1; 2; 3]

Types

type alias
type name     = string
type point    = float * float
type 'a pair = 'a * 'a
record type
type person = {
  name  : string;
  age   : int;
  mutable score : int;
}
let p2 = { p with age = 31 }
variant (ADT)
type shape =
  | Circle    of float
  | Rect      of float * float
  | Point
let s = Circle 5.0
option
let safe_div a b =
  if b = 0 then None
  else Some (a / b)
(* int -> int -> int option *)
result
let parse s =
  match int_of_string_opt s with
  | Some n -> Ok n
  | None   -> Error "not a number"
recursive type
type 'a tree =
  | Leaf
  | Node of 'a * 'a tree * 'a tree

Functions

defining functions
let square x  = x * x
let add x y   = x + y
let sq        = fun x -> x * x
recursive
let rec fact n =
  if n <= 1 then 1
  else n * fact (n - 1)
fact 5  (* 120 *)
labeled & optional args
let greet ?(title="") ~name =
  if title = "" then name
  else title ^ " " ^ name
greet ~title:"Dr." ~name:"Lee"
pipe operator |>
[1;2;3;4;5]
|> List.filter (fun x -> x mod 2 = 0)
|> List.map    (fun x -> x * x)
|> List.fold_left (+) 0  (* 20 *)

Pattern Matching

match expression
match x with
| 0           -> "zero"
| n when n < 0 -> "negative"
| _           -> "positive"
matching variants
let area = function
  | Circle r     -> Float.pi *. r *. r
  | Rect (w, h)  -> w *. h
  | Point        -> 0.0
matching lists
let rec sum = function
  | []      -> 0
  | x :: xs -> x + sum xs
sum [1; 2; 3]  (* 6 *)
nested patterns
match pair with
| (Some x, Some y) -> x + y
| (Some x, None)   -> x
| (None,   _)      -> 0

Lists & Collections

list basics
let xs = [1; 2; 3]
0 :: xs           (* [0;1;2;3] *)
xs @ [4; 5]      (* [1;2;3;4;5] *)
List.length xs    (* 3 *)
map / filter / fold
List.map    (fun x -> x*2) xs
(* [2; 4; 6] *)
List.filter (fun x -> x > 1) xs
(* [2; 3] *)
List.fold_left (+) 0 xs  (* 6 *)
arrays
let a = [| 1; 2; 3 |]
a.(0)           (* 1, read *)
a.(0) <- 99     (* mutate *)
Array.map (fun x -> x+1) a
Hashtbl
let t = Hashtbl.create 16
Hashtbl.add    t "k" 42
Hashtbl.find   t "k"   (* 42 *)
Hashtbl.remove t "k"

Modules

defining a module
module Stack = struct
  type 'a t = 'a list
  let empty    = []
  let push x s = x :: s
end
signature
module type S = sig
  type 'a t
  val empty : 'a t
  val push  : 'a -> 'a t -> 'a t
end
local open (preferred)
let result =
  List.(map (fun x -> x+1)
         [1; 2; 3])
(* avoids polluting scope *)
functor
module StringMap =
  Map.Make(String)

let m =
  StringMap.add "k" 1
    StringMap.empty

I/O & Misc

printing
print_endline "hello"
Printf.printf "%s = %d\n" "x" 42
let s = Printf.sprintf "n=%d" 5
exceptions
exception Bad of string
raise (Bad "oops")

try risky () with
| Bad msg -> print_endline msg
strings
"hello" ^ " world"
String.length "hi"       (* 2 *)
String.sub s 0 5
String.split_on_char ' ' s
control flow
if x > 0 then "pos" else "other"

for i = 0 to 9 do
  print_int i done

while !n > 0 do
  n := !n - 1 done