Non-recursive functions are defined like this:

let f x = ...

Recursive functions are defined like this:

let rec f x = ...

One of the best known recursive functions is the factorial function. In OCaml, it can be written as follows:

(** [fact n] is [n]!.
    Requires: [n >= 0]. *)
$> let rec fact n = if n = 0 then 1 else n * fact (n - 1)
val fact : int -> int = <fun>

Note how we didn’t have to write any types in either of our functions: the OCaml compiler infers them for us automatically.

If we wanted to write down the types for some reason, we could do that:

let rec pow (x : int) (y : int) : int = ...

OCaml supports labeled arguments to functions. You can declare this kind of function using the following syntax:

let f ~name1:arg1 ~name2:arg2 = arg1 + arg2;;

This function can be called by passing the labeled arguments in either order:

f ~name2:3 ~name1:4

Are you ready for the truth? Take a deep breath. Here goes…

Every OCaml function takes exactly one argument.

let f x1 x2 ... xn = e

is semantically equivalent to

let f =
  fun x1 ->
    (fun x2 ->
       (...
          (fun xn -> e)...))

So even though you think of f as a function that takes n arguments, in reality it is a function that takes 1 argument and returns a function.

Operators are functions too:

$> ( + ) 3 4;;
- : int = 7
$> let add3 = ( + ) 3
- : val add3 : int -> int = <fun>
 
$> add3 2
- : int = 5

This concept is useful to define our own operators, for example:

$> let ( ^^ ) x y = max x y
$> let () = 2 ^^ 3
- : int = 3

We can also define a function which receives optional args:

let f ?name:(arg1=8) arg2 = arg1 + arg2

For example:

$> f ~name:2 7
- : int = 9
$> f 7
- : int = 15

Other important concept to understand OCaml functions is “pattern matching”. This is another topic, but this can clarify how to understand it:

https://stackoverflow.com/questions/43005259/explanation-of-ocaml-match-and-function-discrepencies


🌱 Back to Garden