This page gives a practical understanding of functions in Ocaml.
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 *)
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 arguments would be a function with 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› -> … -> ‹expression›
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.
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 *)
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 *)
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.
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.
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.blog comments powered by Disqus