Methods in OCaml

OCaml supports methods defined on record types, which are similar to structs in other languages.

type rect = { width : int; height : int }

(* This area function takes a rect as its first argument *)
let area r = r.width * r.height

(* Methods can be defined for either mutable or immutable types.
   Here's an example of a function that doesn't modify the rect *)
let perim r = 2 * r.width + 2 * r.height

let main () =
  let r = { width = 10; height = 5 } in

  (* Here we call the 2 functions defined for our record *)
  Printf.printf "area: %d\n" (area r);
  Printf.printf "perim: %d\n" (perim r);

  (* OCaml doesn't have pointers in the same way as some other languages,
     but we can create a reference to our rect if we need to *)
  let rref = ref r in
  Printf.printf "area: %d\n" (area !rref);
  Printf.printf "perim: %d\n" (perim !rref)

let () = main ()

To run the program:

$ ocaml methods.ml
area: 50
perim: 30
area: 50
perim: 30

In OCaml, we define functions that operate on our rect type, rather than methods that are attached to the type. The area and perim functions take a rect as their first argument.

OCaml doesn’t have the concept of pointer and value receivers like some other languages. Instead, all values are immutable by default. If you need to modify a value, you would typically create a new value or use a mutable reference.

In the example above, we create a reference rref to demonstrate a similar concept to using a pointer in other languages. However, in idiomatic OCaml, you would typically just pass the value directly.

Next, we’ll look at OCaml’s mechanism for grouping and naming related sets of functions: modules and signatures.