OCaml fundamentals
In OCaml, an expression is a piece of code that can be evaluated to a value. For example, 1 + 2 is an expression that evaluates to the value 3.
Evaluation is the process of computing the value of an expression. Evaluation is performed by the OCaml interpreter or compiler. For example, when the OCaml interpreter encounters the expression 1 + 2, it evaluates it to the value 3.
Here are some examples of expressions, values, and evaluation in OCaml:
Expression: 1 + 2
Value: 3
Evaluation: The OCaml interpreter or compiler adds 1 and 2 to obtain the value 3.
Expression: "Hello, " ^ "world!"
Value: "Hello, world!"
Evaluation: The OCaml interpreter or compiler concatenates the two strings to obtain the value "Hello, world!".
Expression: let x = 1 in x + 2
Value: 3
Evaluation: The OCaml interpreter or compiler first assigns the value 1 to the variable x, then evaluates the expression x + 2 to obtain the value 3.
Functions⌗
The basic syntax for defining a function in OCaml is to use the keyword let, followed by the name of the function, a list of parameters, and the = sign. The body of the function follows the = sign and is executed when the function is called. For example, the following function defines a function called square that takes one argument x and returns its square:
let square x = x * x
Functions in OCaml are defined the same as other values, but they have parameters that are used to receive input when the function is called. Functions are called by providing the argument value, and the function body is executed with the provided value. For example, the square function can be called by providing the argument value 2:
square 2;;
When a function takes multiple arguments, they are separated by spaces, and it is not necessary to use parentheses when calling the function. For example, the following function defines a function called add that takes two arguments x and y and returns their sum:
let add x y = x + y
This function can be called by providing the arguments:
add 2 3;;
However, if the function is called with multiple arguments and the arguments are expressions, it is necessary to use parentheses to indicate the order of evaluation. For example, the following function defines a function called multiple that takes three arguments x, y, and z and returns their product:
let multiple x y z = x * y * z
This function can be called by providing the arguments:
multiple (2+1) (3*4) (5-1);;
It is important to note that in OCaml, function arguments are separated by spaces, not commas, and that the use of parentheses is necessary only to group expressions or indicate the order of evaluation.
Recursive functions⌗
The rec keyword is used to define a function that is recursive, which means that the function calls itself as part of its execution. Recursive functions are a powerful tool that can be used to solve problems that involve repetitive operations or traversing complex data structures.
Here is an example of a recursive function that calculates the factorial of a given number:
let rec factorial n =
    if n <= 1 then 1 else n * factorial (n-1)
In this example, the function factorial takes one argument n, and uses a recursive call to itself to calculate the factorial of n. The if statement is used to check if the value of n is less than or equal to 1, in which case the function returns 1. If n is greater than 1, the function multiplies n by the result of a recursive call to itself with the argument n-1.
For example calling factorial 5 will return 120.
It’s important to note that recursive functions need a base case or termination condition, otherwise it will keep calling itself and will cause stack overflow. In the above example, the base case is when n is less than or equal to 1.
Type inference⌗
OCaml has a powerful type inference system that can automatically determine the types of variables and functions based on their usage, but it also allows for explicit type annotations. For example, the factorial function can be written with explicit types such as:
let rec factorial (n:int) : int = 
    if n <= 1 then 1 else n * factorial(n-1)
The type of the function factorial above is int -> int, which means it is a function that takes an integer as an input and returns an integer as an output. In OCaml, the arrow -> is used to indicate the input and output types of a function. It’s worth noting that this type notation is called “function type” notation and is the standard way of expressing the type of a function in OCaml.
When a function take multiple arguments, the type of the function can be read from left to right, where the type of the first argument is followed by the type of the second argument and so on, separated by the arrow ->, finally followed by the return type of the function.
For example, the type of the multiple function shared above is: int -> int -> int -> int.