OCaml

  • Comments
    • Comments are written between (* and *).
    • Comments can be nested.
  • Variables
    • define and initialise a variable
      #> let x = 50;;
    • it is possible to add type annotations
      #> let (x: int) = 50;;
  • References
    • declare a reference
      #> let x = ref 0;;
    • get the value of a reference
      #> let y = !x;;
    • modify the value of a reference
      #> x := 1;;
    • aliasing a reference
      #> let z = x;;
  • Comparisons
    • Stdlib module
      val (=) : 'a -> 'a -> bool
      e1 = e2 tests for structural equality of e1 and e2. Mutable structures (e.g. references and arrays) are equal if and only if their current contents are structurally equal, even if the two mutable objects are not the same physical object. Equality between functional values raises Invalid_argument. Equality between cyclic data structures may not terminate. Comparison between cyclic structures may not terminate.
      val (<>) : 'a -> 'a -> bool
      Negation of (=).
      val (<) : 'a -> 'a -> bool
      See (>=).
      val (>) : 'a -> 'a -> bool
      See (>=).
      val (<=) : 'a -> 'a -> bool
      See (>=).
      val (>=) : 'a -> 'a -> bool
      Structural ordering functions. These functions coincide with the usual orderings over integers, characters, strings, byte sequences and floating-point numbers, and extend them to a total ordering over all types. The ordering is compatible with (=). As in the case of (=), mutable structures are compared by contents. Comparison between cyclic structures may not terminate.
      val compare : 'a -> 'a -> int
      Returns 0 if x is equal to y, a negative integer if x is less than y, and a positive integer if x is greater than y. The ordering implemented by compare is compatible with the comparison predicates (=), (<) and (>) defined above, with one difference on the treatment of the float value nan.
      val min : 'a -> 'a -> 'a
      Return the smaller of the two arguments. The result is unspecified if one of the arguments contains the float value nan.
      val max : 'a -> 'a -> 'a
      Return the greater of the two arguments. The result is unspecified if one of the arguments contains the float value nan.
      val (==) : 'a -> 'a -> bool
      e1 == e2 tests for physical equality of e1 and e2. On mutable types such as references, arrays, byte sequences, records with mutable fields and objects with mutable instance variables, e1 == e2 is true if and only if physical modification of e1 also affects e2. On non-mutable types, the behaviour of (==) is implementation-dependent; however, it is guaranteed that e1 == e2 implies compare e1 e2 = 0.
      val (!=) : 'a -> 'a -> bool
      Negation of (==).
  • Function
    • define a function
      #> let max a b = if a < b then b else a;;
      or
      #> let max = fun a b -> if a < b then b else a;;
    • define a recursive function
      #> let rec range a b = if a > b then [] else a :: range (a + 1) b;;
    • with type annotations
      #> let rec pow (x : int) (y : int) : int = if y = 0 then 1 else x * pow x (y - 1);;
      use unit if no value is returned
      #> let print_flat_tree (n: node): unit = print_endline (string_of_list (list_of_tree n))
    • to make a function tail recursive
      1. Change the function into a helper function. Add an extra argument: the accumulator, often named acc.
      2. Write a new “main” version of the function that calls the helper. It passes the original base case’s return value as the initial value of the accumulator.
      3. Change the helper function to return the accumulator in the base case.
      4. Change the helper function’s recursive case. It now needs to do the extra work on the accumulator argument, before the recursive call.
      #> let factorial n =
          let rec fact_aux n acc =
              if n = 0 then acc else fact_aux (n - 1) (n * acc) in
                  fact_aux n 1 ;;
      val factorial : int -> int = <fun>
    • parameters can be labelled
      #> let f ~name1:arg1 ~name2:arg2 = arg1 + arg2;;
      #> f ~name2:3 ~name1:4;;
    • labels can be used and no variable names are to be given
      #> let f ~name1 ~name2 = name1 + name2;;
    • the syntax to write both a labeled argument and an explicit type annotation
      #> let f ~name1:(arg1 : int) ~name2:(arg2 : int) = arg1 + arg2;;
    • it is possible to make some arguments optional, a default value is provided
      #> let f ?name:(arg1=8) arg2 = arg1 + arg2;;
    • anonymous function, also called lambda expressions
      #> let inc = fun x -> x + 1;;
    • define mutually recursive functions
      #> let rec even n =
      match n with
          | 0 -> true
          | x -> odd (x - 1)
      and odd n =
          match n with
          | 0 -> false
          | x -> even (x - 1);;
    • The application operator @@ applies the function defined on the left side to the argument defined on the right side
      #> succ @@ 4 + 5;;
      - : int = 10
    • The reverse application operator (a.k.a. pipeline operator) |> applies the function defined on the right side to the argument defined on the left side
      #> 4 + 5 |> succ;;
      - : int = 10
  • Operator
    • =, <, and > are polymorphic.
    • An operator between parentheses is a function
      #> ( + ) ;;
      - : int -> int -> int = <fun>
      #> ( + ) 2 3 ;;
      - : int = 5
    • defining an infix operator
      #> let ( ** ) f g x = x |> g |> f ;;
      val ( ** ) : ('a -> 'b) -> ('c -> 'a) -> 'c -> 'b = <fun>
      #> let g x = x *. x ;;
      val g : float -> float = <fun>
      #> let f x = -. x ;;
      val f : float -> float = <fun>
      #> let _ = (f**g) 1.1 ;;
      - : float = -1.21000000000000019
    • defining a prefix operator
      #> let ( !// ) f x = 1. /. ( f x ) ;;
      val ( !// ) : ('a -> float) -> 'a -> float = <fun>
      #> let f x = x *. x ;;
      val f : float -> float = <fun>
      #> let _ = (!// f) 2. ;;
      - : float = 0.25
  • conditional expressions use if … then … else …
    #> let rec gcd a b = if b = 0 then a else gcd b (a mod b);;
  • Pattern matching
    • _ matches anything.
    • Patterns can be combined
      #> let isvowel c =
          match c with
              'a' | 'e' | 'i' | 'o' | 'u' -> true
              | _ -> false
    • Pattern matching on records
      type node = Node of { left : node; value : int; right : node } | Nil
      If we do not care about the value
      match nd with
          | Nil -> …
          | Node _ -> …
      If we want to get the whole record
      match nd with
          | Nil -> …
          | Node n -> …
      If we want to get the whole record fields
      match nd with
          | Nil -> …
          | Node { left = l; value = v; right = r } -> …
      or with syntactic sugar
      match nd with
          | Nil -> …
          | Node { left; value; right } -> …
      It we want both the whole record and its fields
      match nd with
          | Nil -> …
          | Node { left = l; value = v; right = r } as n -> …
    • function keyword automatically has pattern matching
      #> let foo = function
          0 -> "zero"
          | 1 -> "one"
          | 2 -> "couple"
          | 3 -> "few"
          | _ -> "many";;
  • Data types
    • The Basic types are
      • int: 63-bit signed int on 64-bit processors, or 31-bit signed int on 32-bit processors
      • float: IEEE double-precision floating point
      • bool: Boolean, written either true or false
      • char: 8-bit character
      • string: sequence of 8 bit chars
    • Int module
      val zero : int
      zero is the integer 0.
      val one : int
      one is the integer 1.
      val minus_one : int
      minus_one is the integer -1.
      val neg : int -> int
      neg x is ~-x.
      val add : int -> int -> int
      add x y is the addition x + y.
      val sub : int -> int -> int
      sub x y is the subtraction x - y.
      val mul : int -> int -> int
      mul x y is the multiplication x * y.
      val div : int -> int -> int
      div x y is the division x / y.
      val rem : int -> int -> int
      rem x y is the remainder x mod y.
      val succ : int -> int
      succ x is add x 1.
      val pred : int -> int
      pred x is sub x 1.
      val abs : int -> int
      abs x is the absolute value of x. That is x if x is positive and neg xif x is negative.
      Warning. This may be negative if the argument is Int.min_int.
      val max_int : int
      max_int is the greatest representable integer, 2{^[Sys.int_size - 1]} - 1.
      val min_int : int
      min_int is the smallest representable integer, -2{^[Sys.int_size - 1]}.
    • Strings
      • Use ^ to concatenate two strings.
      • \ is to be used to escape " and \.
      • Quoted strings
        #> {|This is a quoted string, here, neither \ nor " are special characters|};
        #> {delimiter|the end of this|}quoted string is here|delimiter}
      • String module
        val empty : stringReturn an empty string.
        val length : string -> intReturn the length of the string.
        val split_on_char : char -> string -> string listsplit_on_char sep s is the list of all (possibly empty) substrings of s that are delimited by the character sep.
    • Options
      • create an option containing 42
        Some 42
      • create an empty option
        None
      • pattern matching on an option
        #> let extract o =
        match o with
            | Some i -> string_of_int i
            | None -> "";;
      • get the value if not None, otherwise a default value
        #> Option.value (Some 77) ~default:(-1);;
      • Option module
        val is_none : 'a option -> boolis_none o is true if and only if o is None.
        val is_some : 'a option -> boolis_some o is true if and only if o is Some o.
        val get : 'a option -> 'aget o is v if o is Some v and raise otherwise.
        Raises Invalid_argument if o is None.
        val value : 'a option -> default:'a -> 'avalue o ~default is v if o is Some v and default otherwise.
        val map : ('a -> 'b) -> 'a option -> 'b optionmap f o is None if o is None and Some (f v) if o is Some v.
    • Lazy
      • create a lazy expression
        #> let a = lazy ( expr );;
      • force the evaluation of the expression, the result is memoized
        #> let b = force a;;
    • Lists
      • An ordered collection of any number of elements sharing the same type.
      • Syntax
        #> [];;
        #> [1];;
        #> [1; 2];;
        #> [1; 2; 3];;
      • head and tail of a list
        #> List.hd [1; 2; 3];;
        - : int = 1
        #> List.tl [1; 2; 3];;
        - : int list = [2; 3]
      • The cons operator :: adds one element to the front of a list.
        #> 1 :: [2; 3];;
      • The append operator @ combines two lists.
        #> [1] @ [2; 3];;
      • List module
        val cons : 'a -> 'a list -> 'a listAdd one element to the front of a list. cons x xs is the same as x :: xs.
        val hd : 'a list -> 'aReturn the first element of the given list.
        Raises Failure if the list is empty.
        val tl : 'a list -> 'a listReturn the given list without its first element.
        Raises Failure if the list is empty.
        val length : 'a list -> intReturn the length of the list.
        val compare_lengths : 'a list -> 'b list -> intCompare the lengths of two lists, the computation stops after reaching the end of the shortest list.
        val compare_length_with : 'a list -> int -> intCompare the length of a list to an integer, the computation stops after at most len iterations on the list.
        val nth : 'a list -> int -> 'aReturn the n-th element of the given list.
        Raises Failure if the list is too short; Invalid_argument if n is negative.
        val nth_opt : 'a list -> int -> 'a optionReturn the n-th element of the given list. Return None if the list is too short.
        Raises Invalid_argument if n is negative.
        val append : 'a list -> 'a list -> 'a listConcatenate two lists. Same function as the infix operator @. Not tail-recursive (length of the first argument). The @ operator is not tail-recursive either.
        val concat : 'a list list -> 'a list
        val flatten : 'a list list -> 'a list
        Concatenate a list of lists. The elements of the argument are all concatenated together (in the same order) to give the result. Not tail-recursive (length of the argument + length of the longest sub-list).
        val map : ('a -> 'b) -> 'a list -> 'b listApply function f to a1, …, an, and builds the list [f a1; …; f an]. Not tail-recursive.
        val iter : ('a -> unit) -> 'a list -> unititer f [a1; …; an] applies function f in turn to [a1; …; an]. It is equivalent to f a1; f a2; …; f an.
        val map2 : ('a -> 'b -> 'c) -> 'a list -> 'b list -> 'c listmap2 f [a1; …; an] [b1; …; bn] is [f a1 b1; …; f an bn]. Not tail-recursive.
        Raises Invalid_argument if the two lists are determined to have different lengths.
        val iter2 : ('a -> 'b -> unit) -> 'a list -> 'b list -> unititer2 f [a1; …; an] [b1; …; bn] calls in turn f a1 b1; …; f an bn.
        Raises Invalid_argument if the two lists are determined to have different lengths.
        val fold_right : ('a -> 'b -> 'b) -> 'a list -> 'b -> 'bfold_right f [a1; …; an] init is f a1 (f a2 (… (f an init) …)). Not tail-recursive.
        val fold_left : ('a -> 'b -> 'a) -> 'a -> 'b list -> 'afold_left f init [b1; …; bn] is f (… (f (f init b1) b2) …) bn.
        val fold_left_map : ('a -> 'b -> 'a * 'c) -> 'a -> 'b list -> 'a * 'c listfold_left_map is a combination of fold_left and map that threads an accumulator through calls to f.
        val concat_map : ('a -> 'b list) -> 'a list -> 'b listconcat_map f l gives the same result as List.concat (List.map f l). Tail-recursive.
        val mem : 'a -> 'a list -> boolmem a list is true if and only if a is equal to an element of list.
        val memq : 'a -> 'a list -> boolSame as List.mem, but uses physical equality instead of structural equality to compare list elements.
        val for_all : ('a -> bool) -> 'a list -> boolfor_all f [a1; …; an] checks if all elements of the list satisfy the predicate f. That is, it returns (f a1) >> (f a2) >> … >> (f an) for a non-empty list and true if the list is empty.
        val exists : ('a -> bool) -> 'a list -> boolexists f [a1; …; an] checks if at least one element of the list satisfies the predicate f. That is, it returns (f a1) || (f a2) || … || (f an) for a non-empty list and false if the list is empty.
        val for_all2 : ('a -> 'b -> bool) -> 'a list -> 'b list -> boolSame as List.for_all, but for a two-argument predicate.
        Raises Invalid_argument if the two lists are determined to have different lengths.
        val exists2 : ('a -> 'b -> bool) -> 'a list -> 'b list -> boolSame as List.exists, but for a two-argument predicate.
        Raises Invalid_argument if the two lists are determined to have different lengths.
        val find : ('a -> bool) -> 'a list -> 'afind f l returns the first element of the list l that satisfies the predicate f.
        Raises Not_found if there is no value that satisfies fin the list l.
        val find_opt : ('a -> bool) -> 'a list -> 'a optionfind_opt f l returns the first element of the list l that satisfies the predicate f. Returns None if there is no value that satisfies f in the list l.
        val filter : ('a -> bool) -> 'a list -> 'a list
        val find_all : ('a -> bool) -> 'a list -> 'a list
        filter f l returns all the elements of the list l that satisfy the predicate f. The order of the elements in the input list is preserved.
        find_all is another name for filter.
        val partition : ('a -> bool) -> 'a list -> 'a list * 'a listpartition f l returns a pair of lists (l1, l2), where l1 is the list of all the elements of l that satisfy the predicate f, and l2 is the list of all the elements of l that do not satisfy f. The order of the elements in the input list is preserved.
        val assoc : 'a -> ('a * 'b) list -> 'bassoc a l returns the value associated with key a in the list of pairs l. That is, assoc a [ …; (a,b); …] = b if (a,b) is the leftmost binding of a in list l.
        Raises Not_found if there is no value associated with a in the list l.
        val assoc_opt : 'a -> ('a * 'b) list -> 'b optionassoc_opt a l returns the value associated with key a in the list of pairs l. That is, assoc a [ …; (a,b); …] = Some b if (a,b) is the leftmost binding of a in list l.Returns None if there is no value associated with a in the list l.
        val split : ('a * 'b) list -> 'a list * 'b listTransform a list of pairs into a pair of lists: split [(a1,b1); …; (an,bn)] is ([a1; …; an], [b1; …; bn]). Not tail-recursive.
        val combine : 'a list -> 'b list -> ('a * 'b) listTransform a pair of lists into a list of pairs: combine [a1; …; an] [b1; …; bn] is [(a1,b1); …; (an,bn)]. Not tail-recursive.
        Raises Invalid_argument if the two lists have different lengths.
        val sort : ('a -> 'a -> int) -> 'a list -> 'a listSort a list in increasing order according to a comparison function.
    • Tuples
      • A fixed number of elements together. This is useful when a function returns several values, we no not have to define a record.
      • Syntax
        #> (true, 0.0, 0.45, 0.73, "french blue");;
      • Destructuring let
        #> let v = (1, true, "bonjour", 'a');;
        val v : int * bool * string * char = (1, true, "bonjour", 'a')
        #> let (a,b,c,d) = v;;
        val a : int = 1
        val b : bool = true
        val c : string = "bonjour"
        val d : char = 'a'
        This can also be written
        #> let a,b,c,d = v;;
        val a : int = 1
        val b : bool = true
        val c : string = "bonjour"
        val d : char = 'a'
      • We can use tuple as a function argument. This gives a nice syntax, but this is less performant because a tuple need to be built.
        #> let f (x,y) = x + y;;
        val f : int * int -> int = <fun>
        #> f (1,2);;
        - : int = 3
      • syntax to define a type
        #> type square = int * int * int * int * int * int * int * int * int;;
        #> let print_square (sq: square) : unit =
            let (a ,b, c, d, e, f, g, h, i) = sq
            in Printf.printf "%d %d %d\n%d %d %d\n%d %d %d\n" a b c d e f g h i;;
    • Records
      • A fixed number of labelled elements.
      • Syntax
        #> type colour = {websafe : bool; r : float; g : float; b : float; name : string};;
        #> let b = {websafe = true; r = 0.0; g = 0.45; b = 0.73; name = "french blue"};;
      • Use the dot notation to get a field
        #> b.name;;
        or pattern matching
        #> match b with {websafe = _; r = _; g = _; b = _; name = n} -> n;;
        or pattern matching with syntactic sugar if we want to use the same name for both the field and a pattern variable
        #> match b with {websafe ; r ; g ; b ; name } -> name;;;
      • It is possible to copy a record while modifying some fields
        #> let c = { b with websafe = false; name = "bleu français" };;
      • Records may be mutable
        #> type person = {first_name : string; surname : string; mutable age : int};;
        #> let birthday p = p.age <- p.age + 1;;
      • Record types may be recursive
        #> type node = {value : int; next : node};;
        But here, there is no way to construct a value of that type because of the circularity.
    • Fixed-length array
      • A mutable compound data type contain elements of the same type.
        Its elements may be accessed in constant time.
      • Syntax
        #> let arr = [|1; 2; 3|];;
        #> arr.(0) <- 0;;
      • Array module
        val length : 'a array -> intReturn the length (number of elements) of the given array.
        val get : 'a array -> int -> 'aget a n returns the element number n of array a. The first element has number 0.
        You can write a.(n) instead of get a n.
    • Variants
      • A variant type is a collection of constructors.
        type point = float * float
        type shape =
            | Point of point
            | Circle of point * float (* center and radius *)
            | Rect of point * point (* lower-left and upper-right corners *)
        let area = function
            | Point _ -> 0.0
            | Circle (_, r) -> Float.pi *. (r ** 2.0)
            | Rect ((x1, y1), (x2, y2)) ->
                let w = x2 -. x1 in
                let h = y2 -. y1 in
                w *. h
        let center = function
            | Point p -> p
            | Circle (p, _) -> p
            | Rect ((x1, y1), (x2, y2)) -> ((x2 +. x1) /. 2.0, (y2 +. y1) /. 2.0)
  • Printing
    • Built-in print functions: print_char, print_string, print_int, and print_float.
    • print_endline "str" prints a string followed by a newline.
    • print_newline ()) prints a newline.
    • Printf module
      val printf : ('a, out_channel, unit) format -> 'aFormat a message and print it on stdout.
      val eprintf : ('a, out_channel, unit) format -> 'aFormat a message and print it on stderr.
  • Stdlib module
    • This module is automatically opened at the beginning of each compilation.
    • val ignore : 'a -> unitDiscard the value of its argument and return (). For instance, ignore(f x) discards the result of the side-effecting function f. It is equivalent to f x; (), except that the latter may generate a compiler warning; writing ignore(f x) instead avoids the warning.
      val print_char : char -> unitPrint a character on standard output.
      val print_string : string -> unitPrint a string on standard output.
      val print_bytes : bytes -> unitPrint a byte sequence on standard output.
      val print_int : int -> unitPrint an integer, in decimal, on standard output.
      val print_float : float -> unitPrint a floating-point number, in decimal, on standard output.
      val print_endline : string -> unitPrint a string, followed by a newline character, on standard output and flush standard output.
      val print_newline : unit -> unitPrint a newline character on standard output, and flush standard output. This can be used to simulate line buffering of standard output.
      val float_of_int : int -> float
      val float : int -> float
      Convert an integer to floating-point.
      val int_of_float : float -> int
      val truncate : float -> int
      Truncate the given floating-point number to an integer. The result is unspecified if the argument is nan or falls outside the range of representable integers.
      val int_of_string_opt : string -> int optionConvert the given string to an integer. The string is read in decimal (by default, or if the string begins with 0u), in hexadecimal (if it begins with 0x or 0X), in octal (if it begins with 0o or 0O), or in binary (if it begins with 0b or 0B).
      The 0u prefix reads the input as an unsigned integer in the range [0, 2*max_int+1]. If the input exceeds max_int it is converted to the signed integer min_int + input - max_int - 1.
      The _ (underscore) character can appear anywhere in the string and is ignored.
      Return None if the given string is not a valid representation of an integer, or if the integer represented exceeds the range of integers representable in type int.
      val int_of_string : string -> intSame as int_of_string_opt, but raise Failure "int_of_string" instead of returning None.
      val fst : 'a * 'b -> 'aReturn the first component of a pair.
      val snd : 'a * 'b -> 'bReturn the second component of a pair.
  • Sys module
    val argv : string arrayThe command line arguments given to the process. The first element is the command name used to invoke the program. The following elements are the command-line arguments given to the program.
    let seed = int_of_string Sys.argv.(1)
  • Random module
    val int : int -> intReturn a random integer between 0 (inclusive) and bound (exclusive). bound must be greater than 0 and less than 230.
    val init : int -> unitInitialize the domain-local generator, using the argument as a seed. The same seed will always yield the same sequence of numbers.
    val full_init : int array -> unitSame as Random.init but takes more data as seed.
    val self_init : unit -> unitInitialize the domain-local generator with a random seed chosen in a system-dependent way. If /dev/urandom is available on the host machine, it is used to provide a highly random initial seed. Otherwise, a less random seed is computed from system parameters (current time, process IDs, domain-local state).
    let _ = Random.self_init ()
    let a = Random.int 999
  • Exceptions
    • define an exception
      #> exception Error ;;
      exception Error
      #> exception Unix_error of string ;;
      exception Unix_error of string
    • raise an exception
      #> raise ( Unix_error "File not found" ) ;;
      Exception: Unix_error "File not found".
    • catching an exception
      #> let safe_divide x y =
          try ( x / y ) with
              | Division_by_zero -> 666 ;;
      val safe_divide : int -> int -> int = <fun>
      #> safe_divide 1 0 ;;
      - : int = 666
    • There are some predefined exceptions.
      • Exit can be used to terminate an iteration, like a break statement.
      • Not_found should be raised when searching failed because there isn't anything satisfactory to be found.
      • Invalid_argument should be raised when a parameter can't be accepted.
        It can be raised using val invalid_arg : string -> 'a
      • Failure should be raised when a result can't be produced.
        It can be raised using val failwith : string -> 'a
    • Example: verifying the command lines arguments
      let start = if (Array.length Sys.argv) != 2 then invalid_arg ("Syntax: " ^ Sys.argv.(0) ^ " <seed>"); int_of_string Sys.argv.(1)
  • Loops
    • Three types of loops
      • while e1 do e2 done
      • for x=e1 to e2 do e3 done
      • for x=e1 downto e2 do e3 done
  • Zarith: arithmetic and logical operations over arbitrary-precision integers
    • example
      open Z

      let c =
          let a = Z.of_string "12345678901234567890" in
          let b = Z.of_string "98765432109876543210" in
          a + b

      let _ = Printf.printf "Sum: %s\n" (Z.to_string c);
    • Z module
      type tType of integers of arbitrary length.
      exception OverflowRaised by conversion functions when the value cannot be represented in the destination type.
      val zero : tThe number 0.
      val one : tThe number 1.
      val minus_one : tThe number -1.
      val of_int : int -> tConverts from a base integer.
      val to_int : t -> intConverts to a base integer. May raise an Overflow.
      val of_string : string -> tConverts a string to an integer.
      An optional - prefix indicates a negative number, while a + prefix is ignored.
      An optional prefix 0x, 0o, or 0b (following the optional - or + prefix) indicates that the number is, represented, in hexadecimal, octal, or binary, respectively.
      Otherwise, base 10 is assumed. (Unlike C, a lone 0 prefix does not denote octal.)
      val to_string : t -> stringGives a human-readable, decimal string representation of the argument.
      val add : t -> t -> t
      val (+) : t -> t -> t
      Addition.
      val succ : t -> tReturns its argument plus one.
      val pred : t -> tReturns its argument minus one.
      val sub : t -> t -> t
      val (-) : t -> t -> t
      Subtraction .
      val shift_left : t -> int -> tShifts to the left. Equivalent to a multiplication by a power of 2. The second argument must be non-negative.
      val shift_right : t -> int -> tShifts to the right. This is an arithmetic shift, equivalent to a division by a power of 2 with rounding towards -oo. The second argument must be non-negative.
      val shift_right_trunc : t -> int -> tShifts to the right, rounding towards 0. This is equivalent to a division by a power of 2, with truncation. The second argument must be non-negative
  • Installation
    • Using Docker
      • a simple installation process:
        docker run --name ocaml -it ocaml/opam:ubuntu-22.04-ocaml-4.13 bash
        in the container
        opam install utop
        exit
      • then use this container with
        docker start ocaml
        docker exec -it ocaml bash
        in the container
        eval $(opam env)
        utop
        …
      • at the end, exit from utop
        exit 0;;
        exit from the container
        exit
        stop the container
        docker stop ocaml
  • Set up the environment
    • on Linux
      #> eval $(opam env)
    • on all OSes, to run a command with the environment being set up
      #> opam exec <cmd>
  • Tools
    • ocamlc
      • Compile to bytecodes
        #> ocamlc foobar.ml
        On most systems, the file produced by the linking phase can be run directly
        #> ./camlprog.exe
      • ocamlc can take in input
        • .ml which are taken to be source files
        • .mli which are taken to be source files for compilation unit interfaces
        • .cmo which are taken to be compiled object bytecode
        • .cma which are taken taken to be libraries of object bytecode (generated with ocaml -a)
        • .c which are taken taken to be C sources files, assed to the C compiler, which generates a .o/.obj object file
        • .o (.obj on Windows) which are assumed to be C object files
        • .a (.lib on Windows) which are assumed to be C libraries
        • .so (.dll on Windows) which are assumed to be C shared libraries
      • When compiling a .ml
        • If a .mli file already exists, ocamlc checks that it checks that the .ml repects it.
          Otherwise it generates one.
        • ocamlc generates a .cmo.
        • ocamlc generates a bytecode file a.out (camlprog.exe on Windows).
      • Compile to bytecodes with debug information and run with stacktrace dump
        #> ocamlc -g foobar.ml
        #> OCAMLRUNPARAM=b ./camlprog.exe
    • ocamlrun
      • Run a bytecode file.
        Most of the time, bytecode files can be run directly, without using ocamlrun.
    • ocamldebug
      • Start the debugger
        #> ocamldebug camlprog.exe
    • opam
      • Initialise the ~/.opam directory
        #> opam init
      • Synchronize opam's database with the package repositories
        #> opam update
      • List installed packages
        #> opam list
      • List all available packages
        #> opam list -a
      • Install the package <name>
        #> opam install <name>
      • It is possible to constrain the version to install
        #> opam install <name>.<version>
        #> opam install "<name>>=<version>"
      • Upgrade package <name>
        #> opam upgrade <name>
      • Upgrade all installed package <name>
        #> opam upgrade
      • Uninstall the package <name>
        #> opam remove <name>
      • Prints appropriate shell variable assignments to stdout
        #> opam env
        To be used as
        #> eval $(opam env)
    • dune
      • Initialise the project <project_name>
        #> dune init proj <project_name>
      • Build the project in the current directory
        #> dune build
      • Run the tests of the project in the current directory
        #> dune test
      • Run the project
        #> dune exec <project_name>

See also: links
Last update: September 29th, 2024
🧭
✉️
🔎