OCaml Tutorial: Function
This page gives a practical understanding of functions in Ocaml.
Function with One Parameter
To define a function, use the form:
function parameter_name = expression
(* a function that returns its argument + 1 *) function n -> n + 1 ;; (* applying the function to the value 2 *) (function n -> n + 1) 2;; (* ⇒ 3 *)
Function with More Than One Parameters
To define a function with 2 parameters, you do it by defining a function with 1 parameter, that returns another function of 1 parameter. The form is this:
function parameter -> function parameter -> expression
The following is a example:
(* defining a function “f(x,y)” that computes x + y *) function x -> ( function y -> x + y );; (* applying the function to values *) (function x -> ( function y -> x + y) ) 3 4;; (* ⇒ 7 *)
In the above example, the line
function x -> ( function y -> x + y ), means a function with parameter x, which returns
function y -> x + y, which is a function with parameter y, and computes
x + y.
The number of parameters of a function is called its “arity”. So, a function with 2 parameters is a function of arity 2.
To define a function with 3 or more parameters, the same pattern is used.
function parameter_1 ->
function parameter_2 ->
function parameter_3 ->
At the language core, all multi-parameter functions are decomposed into a sequence of functions of 1 parameter.
There is a syntax shortcut for defining functions of multiple parameters. The form is:
fun parameter_1 parameter_2 parameter_3 … -> expression
fun x y -> x + y;; (fun x y -> x + y) 3 4;; (* ⇒ 7 *)
This is the more practical way to define a function.
Assign Name to Function
A function can be assigned to a variable, thus giving it a name.
let sumOfTwo = fun x y -> x + y;; (* giving function a name *) sumOfTwo 3 4;; (* ⇒ 7 *)
Syntax Shortcut for Defining a Function
let name = fun params -> expr is used often, so that there is a shortcut. The shortcut form is:
let function_name param1 param2 … = expression
(* the following are all equivalent *) let sumOfTwo = function x -> function y -> x + y;; let sumOfTwo = fun x y -> x + y;; let sumOfTwo x y = x + y;; sumOfTwo 3 4;; (* ⇒ 7 *)
Operator Precedence of Function Syntax
The operator for function definition
-> is more sticky to the right. This means, when you have
stuff1 -> stuff2 -> stuff3, ocaml will interpret it as
stuff1 -> ( stuff2 -> stuff3 ).
This means when you define a function that returns a function, you don't have to use parenthesis.
However, function application in ocaml favors the left side.
If you write
f g h x;;, ocaml will interpret it as
((f g) h) x;;. This is particular important to know when
you use functions of multiple arguments. Here's some examples:
let f s = s ^ "1";; (* append 1 to a string *) let g s = s ^ "2";; (* append 2 to a string *) let h s = s ^ "3";; (* append 3 to a string *) h (g (f "x"));; (* ⇒ "x123" *)
In the above, if you use
f g h "x";;, the compiler will give a error:
# Characters 0-1: f g h "x";; ^ Error: This function is applied to too many arguments, maybe you forgot a `;'
Because it starts by computing
f(g). This results in a error right away, because
by your definition, f has one parameter of type string, and returns a string, but you are trying to apply the result to
If you call
((f g) h) "x", then the error is more clear:
((f g) h) "x";; ^ Error: This expression has type string -> string but is here used with type string
The error says “but is here used with type string” because your function g is defined to be of type “string → string”, and you are feeding g to f, which expect a string.
Using Operator as Function
Operators, such as “+ *” etc, can be considered as functions of 2 parameters. They can be used as a function in ocaml. A function call has the form “f arg1 arg2”, while operator such as “+” is used in the form “arg1 + arg2”. Sometimes it is useful to call operators in the function form, so that the power of function and its syntax fully apply to all operators.
To use operator in the form of a function, the operator must be bracketed with paren. The form is:
(operator_symbol) arg1 arg2
( + ) 3 4;; (* ⇒ 7 *) ( *. ) 23. 3.;; (* ⇒ 69. *) ( + ) ((+) 3 4) 5;; (* ⇒ 12 *) ( * ) ((+) 3 4) 5;; (* ⇒ 35 *)
Note that extra paren for grouping is necessary.
Defining Your Own Operator
You can define your own operator. The form is:
let ( symbol_chars ) left_arg right_arg = expression
(* define operator for vector addition of 2 dimensional vectors *) (* using 2-tuple as vectors *) let ( @+ ) vec1 vec2 = ( (fst vec1)+(fst vec2), (snd vec1)+(snd vec2) ) ;; (3,4) @+ (5,6);; (* ⇒ (8,10) *)
Note: the char sequence used for operator is limited to symbol chars, such as “! @ # $ % ^ & *”. They cannot letters, numbers, nor Unicode char.
Functions that are defined by referring to itself, must be declared with “rec”.
(* example of factorial function *) let rec f n = if n == 1 then 1 else n * f (n-1);; f 3 (* ⇒ 6 *) (* example of fibonacci sequence. *) (* nth term is sum of previous 2 terms. Starting with 0 and 1. *) let rec f n = match n with 0 -> 0 | 1 -> 1 | x -> f (n-1) + f (n-2);; f 9;; (* ⇒ 34 *)
Note: above recursive definitions are for example only. They are very inefficient.