OCaml CHEAT SHEET
The OCaml cheat sheet is a one-page reference sheet for the OCaml programming language.
#Getting Started
let () =
let message = "Hello, World!" in
Printf.printf "%s\n" message
Compile and Run
$ ocamlc -o hello.byte hello.ml
$ ./hello.byte
Build and Run with Dune
$ dune build hello.exe
$ _build/default/hello.exe
# you can also just run
$ dune exec ./hello.exe
See the dune documentation for more info.
Install modules with opam
$ opam install hex
Global Open
open Hex
Local Open
Hex.of_string "hex string"
let open Hex in
of_string "to hex"
Line & Block Comments
(* A single line comment *)
(* A multi-line comment
* where we want to explain
* something complex *)
(* Outer comment
(* Nested comment *)
End of outer comment *)
Documentation Comments
val sum : int -> int -> int
(** [sum x y] returns the sum
of two integers [x] and [y] *)
#Data Types
Unit
Note: # Indicates execution at the toplevel followed by the output
# ();; (* equivalent to void in C *)
- : unit = ()
Basic Types
# 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}
Options & Results
# Some 42;;
- : int option = Some 42
# Ok 42;;
- : (int, 'a) result = Ok 42
# Error "404";;
- : ('a, int) result = Error 404
Arrays
# [|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|]
Lists
# [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]
Records
Bundle related data
type person = {
name: string;
age: int
}
# let zeno = {name = "Zeno"; age = 30};;
val zeno : person = {name = "Zeno"; age = 30}
Variants
Several different, but related types
type shape =
| Circle of float
| Rectangle of float * float
# let my_shape = Circle 5.0;;
- : shape = Circle 5.
Aliases
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.)
#Functions
Single parameter
let add_one x =
let result = x + 1 in
result
# add_one 1;;
- : int = 2
Multiple parameters
let sum x y =
let result = x + y in
result
# sum 1 2;;
- : int = 3
Tuple parameter
let str_concat (x, y) =
x ^ " " ^ y
# str_concat ("Hello", "OCaml") ;;
- : string = "Hello Ocaml"
rec keyword
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.
Tail Recursion
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
Application Operator
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...
Pipeline
(* 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
#Control Flow
If Statement
let is_pos x =
if x > 0 then "positive" else "negative"
If else if
let f x =
if x > 3 then "gt 3"
else if x < 3 then "lt 3"
else "eq 3"
Pattern Matching
let is_pos x =
match x > 0 with
| true -> "positive"
| false -> "negative"
For loop
for i = 1 to 5 do
print_int i
done
While loop
Notice the ref is needed to have the while condition eventually become false.
let i = ref 0 in
while !i < 5 do
print_int !i;
i := !i + 1
done
Comparison Operators
= (* equal to *)
<> (* not equal to *)
> (* greater than *)
< (* less than *)
>= (* greater than or eq to *)
<= (* less than or eq to *)
Arithmatic Operators
(* int operator float operator *)
+ +. (* addition *)
- -. (* subtraction *)
* *. (* multiplication *)
/ /. (* division *)
** (* power *)
#Useful Tools
Searching & Filtering
# 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]
Applying Transformations
(* 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
Definition and Access
let scores =
[("math", 91); ("phil", 89); ("stats", 94)]
# List.assoc "stats" scores;;
- : int = 94
# List.mem_assoc "math" scores;;
- : bool = true
Split and Combine
# 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.
Initialize & Add Data
# 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";;
Find Data
# 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.
Initialization & Add Data
(* 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)
Finding Entries
(* 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)
Adding & Removing Entries
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
Printing Data
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