The OCaml cheat sheet is a one-page reference sheet for the OCaml programming language.
Note: #
Indicates execution at the toplevel followed by the output
# ();; (* equivalent to void in C *)
- : unit = ()
# 5 ;; (* integer *)
- : int = 5
# 3.14 ;; (* float *)
- : float = 3.14
# true ;; (* bool *)
- : bool = true
# false ;;
- : bool = false
# 'a' ;; (* char *)
- : char = 'a'
# "a string" ;; (* string *)
- : string = "a string"
# String.to_bytes "hello" ;; (* bytes *)
- : bytes = Bytes.of_string "hello"
# (3, 5);; (* tuple *)
- : int * int = (3, 5)
# ref 0;; (* reference *)
- : int ref = {contents = 0}
# Some 42;;
- : int option = Some 42
# Ok 42;;
- : (int, 'a) result = Ok 42
# Error "404";;
- : ('a, int) result = Error 404
# [|0; 1; 2; 3|];; (* create an array *)
- : int array = [|0; 1; 2; 3|]
# [|'u'; 's'; 'c'|].(1);; (* array access *)
- char = 's'
Arrays are mutable
let scores = [|97; 85; 99|];;
- : int array = [|97; 85; 99|]
# scores.(2) <- 89;; (* update an element *)
- unit = ()
# scores;;
- : int array = [|97; 85; 89|]
# [1; 2; 3];;
- : int list = [1; 2; 3;]
# ["a"; "str"; "lst"];;
- : string list = ["a"; "str"; "lst"]
Lists are immutable
# let lst = [1; 2; 3];;
- : int list = [1; 2; 3]
# let new_lst = 0 :: lst;; (* prepend to a new list *)
- : int list = [0; 1; 2; 3]
# new_lst @ [4;5;6];; (* combine two lists *)
- : int list = [0; 1; 2; 3; 4; 5; 6]
Bundle related data
type person = {
name: string;
age: int
}
# let zeno = {name = "Zeno"; age = 30};;
val zeno : person = {name = "Zeno"; age = 30}
Several different, but related types
type shape =
| Circle of float
| Rectangle of float * float
# let my_shape = Circle 5.0;;
- : shape = Circle 5.
Provide meaningful name to complex or commonly used types
type point = float * float
# let origin: point = (0.0, 0.0);;
val origin : point = (0., 0.)
All recusive functions use the rec keyword
let rec factorial n =
if n < 1 then 1 else n * factorial (n - 1)
The above can cause stackoverflow.
Makes use of a helper function and the acc argument.
let rec factorial_helper n acc =
if n = 0 then acc
else factorial_helper (n - 1) (n * acc)
Notice the last call is the recursive function.
let factorial n = factorial_helper n 1
Read from right to left, the first operation is sum 2 3
(* find log(2 + 3) *)
# log @@ float_of_int @@ sum 2 3 ;;
- : float = 1.609...
(* find log((x + y)!) *)
# sum 2 3
|> factorial
|> float_of_int
|> log ;;
- : float = 4.787...
|>
takes the output of the function and passes it as input to the next function in the pipeline
= (* equal to *)
<> (* not equal to *)
> (* greater than *)
< (* less than *)
>= (* greater than or eq to *)
<= (* less than or eq to *)
(* int operator float operator *)
+ +. (* addition *)
- -. (* subtraction *)
* *. (* multiplication *)
/ /. (* division *)
** (* power *)
# let lst = [1; 2; 3];;
val lst : int list = [1; 2; 3]
# List.filter (fun x -> x mod 2 = 0) lst;;
- : int list = [2]
# List.find (fun x -> x = 4) lst;;
Exception: Not_found
# List.sort compare [2; 1; 3];;
- : int list = [1; 2; 3]
(* Loop over list and apply fun f *)
List.iter f lst
(* map a function to each elem *)
(* Ex. double each element x in lst *)
List.map (fun x -> x + x) lst
(* Apply an operator between elements *)
(* Ex. 1 + 2 + 3 *)
List.fold_left (+) 0 lst
let scores =
[("math", 91); ("phil", 89); ("stats", 94)]
# List.assoc "stats" scores;;
- : int = 94
# List.mem_assoc "math" scores;;
- : bool = true
# List.split scores;;
- : string list * int list = (["math"; "phil"; "stats"], [91; 89; 94])
# List.combine [1;2;3] [4; 5; 6];;
- : (int * int) list = [(1, 4); (2, 5); (3, 6)]
Association lists are similar to dictionaries or hashmaps
Hash Tables are mutable.
# let my_htable = Hashtbl.create 3;;
val my_htable : ('_weak1, '_weak2) Hashtbl.t = <abstr>
# Hashtbl.add my_htable "A" "John";
Hashtbl.add my_htable "A" "Jane";
Hashtbl.add my_htable "B" "Max";;
# Hashtbl.find my_htable "A";;
- : string = "Jane"
(* find all *)
# Hashtbl.find_all my_htable "A";;
- : string list = ["Jane"; "John"]
Maps are immutable key-value association tables.
(* the Map.Make functor creates the custom map module *)
# module StringMap = Map.Make(String);;
let books =
StringMap.empty
|> StringMap.add "Dune" ("Herbet", 1965)
|> StringMap.add "Neuromancer" ("Gibson", 1984)
(* find_opt returns assoc val wrapped in an option else None *)
# StringMap.find_opt "Dune" books;;
- : (string * int) option = Some ("Herbet", 1965)
(* find returns the association else Not_Found *)
# StringMap.find "Dune" books;;
- : string * int = ("Herbet", 1965)
Creates a new map since maps are immutable
let more_books = books
|> StringMap.add "Foundation" ("Isaac Asimov", 1951)
let less_books =
|> StringMap.remove "Dune"
Filtering
let eighties_books =
StringMap.filter
(fun _ (_, year) -> year > 1980 & number < 1990) books
let print_books map =
StringMap.iter (fun title (author, year) ->
Printf.printf "Title: %s, Author: %s, Year: %d\n" title author year
) map
# let () = print_books eighties_books;;
Title: Neuromancer, Author: Gibson, Year: 1984