Skip to content

jonowoodhouse/Ocaml_cheatsheet

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

33 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

OCaml Cheatsheet

View the cheatsheet.ml source code file for great examples of using Ocaml.

open Core

let () = print_endline "hello world"

let variables_example =
  (* ------------------------------------------------------------
     Variables
     ------------------------------------------------------------ *)
  let x = 5 in
  let real = 9. (* float (no trailing zero required) *) in
  let s = "a string" in

  (* ------------------------------------------------------------
     Annotated variables
     ------------------------------------------------------------ *)
  let y : int = 6 in
  let (z : int) = 7 in

  (* ------------------------------------------------------------
     Annotated return type - [calc] returns an int
     ------------------------------------------------------------ *)
  let calc x y s : int =
    printf "A %s has %i lives\n" s (x + y);
    x + y
  in

  (* ------------------------------------------------------------
     Renaming arguments
     ------------------------------------------------------------ *)
  let f ~a:renamed_a = renamed_a * 2 in

  (* ------------------------------------------------------------
     Printing to the screen
     ------------------------------------------------------------ *)
  printf "%d %d %d %f %s %i\n" x y z real s (f ~a:50);
  print_s [%message "Description" (s : string)];
  print_s (String.sexp_of_t s);
  (* This uses: https://github.com/janestreet/ppx_custom_printf*)
  printf !"%{sexp:string} %{sexp#mach:string} %{String}\n" s s s;
  let (_ : int) = calc 5 4 "cat" in

  (* ------------------------------------------------------------
     Recursion
     ------------------------------------------------------------ *)
  let rec fold list ~init ~accum =
    match list with [] -> init | hd :: tl -> fold tl ~init:(accum init hd) ~accum
  in

  (* ------------------------------------------------------------
     Anonymous function (fun keyword)
     ------------------------------------------------------------ *)
  printf "%i\n" (fold [ 1; 2; 3 ] ~init:0 ~accum:(fun init elem -> init + elem))

(* ------------------------------------------------------------
   Records - Construction, destruction, annotation and renaming
   ------------------------------------------------------------ *)
type contact = { name : string; mobile : string; birth_year : int } [@@deriving sexp]

let records_example =
  (* record construction *)
  let c = { name = "Adam"; mobile = "012345678"; birth_year = 1995 } in
  printf "%s %s %i\n" c.name c.mobile c.birth_year;
  printf !"%{sexp:contact}\n" c;
  let create_contact name mobile birth_year = { name; mobile; birth_year } in
  let c2 = create_contact "James" "999999999" 1988 in
  (* Use dot notation *)
  let print1 x = printf "%s %s %i\n" x.name x.mobile x.birth_year in
  (* Use record deconstruction *)
  let print2 { name; mobile; birth_year } (* much better *) =
    printf "%s %s %i\n" name mobile birth_year
  in
  (* use argument renaming and annotated variable *)
  let print3 ({ name; mobile; birth_year = b } : contact) = printf "%s %s %i\n" name mobile b in
  let print4 c =
    (* use record deconstruction *)
    let { name = n; mobile = m; birth_year } = c in
    printf "%s %s %i\n" n m birth_year
  in
  print1 c;
  print2 c;
  print3 c;
  print4 c2

(* ------------------------------------------------------------
   Record Types - records (types) in modules
   ------------------------------------------------------------ *)
module File = struct
  type t = { file_name : string; size : int; attributes : int } [@@deriving sexp]

  let to_string t = if t.attributes > 700 then String.uppercase t.file_name else t.file_name
end

let record_types_example1 =
  let create_directory_entry file_name size attributes = { File.file_name; size; attributes } in
  let is_small_file file =
    let { File.file_name = _; size; attributes = _ } = file in
    size < 1000
  in
  let file = create_directory_entry "temp.log" 100 755 in
  printf !"%{sexp:File.t}\n" file;
  (* ppx uses File.to_string *)
  printf !"%{File} : is_small_file=%b\n" file (is_small_file file)

(* ------------------------------------------------------------
   Record Types - 2nd example
   ------------------------------------------------------------ *)
module Price = struct
  type t = { x : float }

  let create x = { x }
end

let record_types_example2 =
  let price1 = Price.create 5.50 in
  let (price2 : Price.t) = { x = 6.50 } in
  (ignore price1, price2)

(* ------------------------------------------------------------
   Default arguments, named parameters and optional arguments
   ------------------------------------------------------------ *)
let arguments_example =
  (* by is optional but resolves to type int (not opional int)*)
  let increment ?(by = 1) x = x + by in
  let inc ?by x = match by with None -> x + 1 | Some by -> x + by in
  let incr ~by x = x + by in
  printf "0 inc = %d %d %d\n" (increment 0) (inc 0) (incr 0 ~by:1);
  printf "0 inc by 2 = %d %d %d %d\n" (increment 0 ~by:2) (inc 0 ~by:2) (inc 0 ?by:(Some 2))
    (incr 0 ~by:2)

(* ------------------------------------------------------------
   Tuples/Pairs (often better to use a record though)
   Open modules
   ------------------------------------------------------------ *)
let tuples_example =
  let gps_position latitude longitude = (latitude, longitude) in
  let sydney = gps_position (-33.865143) 151.209900 in
  let google_maps gps =
    let open Float in
    "https://www.google.com/maps/search/" ^ to_string (fst gps) ^ "," ^ to_string (snd gps) ^ "/"
  in
  printf "Google Maps URL for Sydney is %s\n" (google_maps sydney)


OCaml Terminology

Term Definition
annonymous function fun i -> 2 * i
applicative Some modules aren't quite monads. They have a [map] function like a Monad but not a [bind] function. [Command] is an example of a Applicative.
capitalisation Modules are Capitalised. functions and values are not.
destructive substitution with type t:=t (TODO explain more)
early binding runs at app start e.g. let two_pi = 2.0 *. Float.pi
first-order functions Functions that operate on normal data elements (e.g. ints, strings, records, variants etc.) See also high-order functions.
high-order functions Functions that take other functions as arguments or return functions. See also first-order functions
identity function Fn.id
interface, signature, module type are all used interchangeably
polymorphic functions functions that act over values with many different types. Similar to templates in C++ and Generics in C# and Java
record A bit like a struct in C.
type person = {age : int; name : string}
record type A record inside a module. module Foo = struct
type t = {bar : int; baz : string }
end
type parameter ['a] is a type parameter. Also known as a type variable. Forms a paramaterised type in a 'a pair.
val used in signatures, module signatures or in .mli files
variant type color = | Red | Green | Blue
variant - polymorphic variant `Red `Green `Blue etc.

Compiling cheatsheet.ml

  • See My OCaml programming environment section below
  • from the shell run this in linux:
	eval `opam config env`
	dune build @all
	_build/default/cheatsheet.exe

My OCaml programming environment

Useful links

Opam

# TODO: complete this list
opam install dune utop ocamlformat core async merlin

Dune

in an empty folder:

	eval `opam config env`
	dune init executable dune_example
	dune build @all
	_build/default/main.exe

Ocamlformat

  • Requires an empty .ocamformat file in the project folder
  • ocamlformat -i cheatsheet.ml

Other Tips

  • Other cool tips will go here

Further Reading

TODO

  • Opam install list
  • Test on a new Ubuntu environment
  • Spacemacs and installation instructions

Releases

No releases published

Packages

No packages published