INF 231 - Functional Algorithmic and Programming

Lecture 2: Identifiers and functions

Identifiers: Global definition

In [1]:
let x = 1 ;;
let y = 2 ;;
let y = x+1 ;;
y ;;

let x = 10 ;;
y ;;

let a = 2 and b = a+1 ;;
Out[1]:
val x : int = 1
Out[1]:
val y : int = 2
Out[1]:
val y : int = 2
Out[1]:
- : int = 2
Out[1]:
val x : int = 10
Out[1]:
- : int = 2
File "[1]", line 9, characters 18-19:
Error: Unbound value a
   8: 
   9: let a = 2 and b = a+1 ;;
  10: ;;

This does not work because $\texttt{a}$ is not in the context where $\texttt{b}$ is computed.

Identifiers: Local definition

In [23]:
let x = 4 in x * x ;;
let a = 2 in a + 1 ;;

let term1 = 10 and term2 = 0 in term1 * term2;;

let a = 1 in let b = a+1 in let c = a+b in let d = a+b+c in d ;;

let a = 10 and b = 3 and c = 5 ;; (* we need to define three identifiers a, b and c for the next expression *)

let discriminant = b*b - 4*a*c in
        if discriminant > 0 then 2
        else if discriminant = 0 then 1
        else 0 ;;

let e = let prod = 4*3*2 in prod*prod+prod+2 ;;
Out[23]:
- : int = 16
Out[23]:
- : int = 3
Out[23]:
- : int = 0
Out[23]:
- : int = 6
Out[23]:
val a : int = 10
val b : int = 3
val c : int = 5
Out[23]:
- : int = 0
Out[23]:
val e : int = 602

Anonymous functions

In [19]:
fun x -> x ;;
Out[19]:
- : 'a -> 'a = <fun>

As you can notice the type of this function is $\texttt{'a -> 'a}$ which is $\texttt{any_type -> any_type}$ (note that the "departure type" and the "arriving" type should be the same - it can be any type. We say that this function is polymorphic -- as we shall see later in the lecture.

Below are three equivalent anonymous functions computing the absolute value.

In [20]:
fun a -> 
  if a < 0 then -a 
  else a;;
  
function a -> 
  if a < 0 then -a 
  else a ;;

fun (a:int) -> 
  if a < 0 then -a 
else a ;;
Out[20]:
- : int -> int = <fun>
Out[20]:
- : int -> int = <fun>
Out[20]:
- : int -> int = <fun>

Defining functions

Below are several equivalent ways to define the identy function (except that some are polymorphic). Remember that we choose to explicitely mention the parameter's types and the result type.

In [21]:
let identity = function x -> x ;;
let identity = fun x -> x ;;
let identity = function (x:int) -> x ;;
let identity = fun (x:int) -> x ;;
let identity x = x ;;
let identity (x:int):int = x ;;
Out[21]:
val identity : 'a -> 'a = <fun>
Out[21]:
val identity : 'a -> 'a = <fun>
Out[21]:
val identity : int -> int = <fun>
Out[21]:
val identity : int -> int = <fun>
Out[21]:
val identity : 'a -> 'a = <fun>
Out[21]:
val identity : int -> int = <fun>

Note that explicitely indicating the type does not forbid to be polymorphic as demonstrated by the function below.

In [24]:
let identity (x:'a):'a = x ;;

let is_zero (x:int): bool = x=0 ;;
let successor (x:int):int = x+1 ;;

let surface (length:float) (width:float):float = length *.width ;;

let surface_circle (radius:float):float = 
        let pi = 3.14 in pi *. (radius**2.);;
Out[24]:
val identity : 'a -> 'a = <fun>
Out[24]:
val is_zero : int -> bool = <fun>
Out[24]:
val successor : int -> int = <fun>
Out[24]:
val surface : float -> float -> float = <fun>
Out[24]:
val surface_circle : float -> float = <fun>

Using Functions

In [10]:
identity x ;;
identity (x) ;;

(fun (x:int) -> x+1) 3 ;;

surface_circle 9.76 ;;
Out[10]:
- : int = 10
Out[10]:
- : int = 10
Out[10]:
- : int = 4
Out[10]:
- : float = 299.108864

Defining functions locally

In [13]:
let successor2 (x:int):int=x+1 in successor2 10 ;;
Out[13]:
- : int = 11

The command below shows that $\texttt{successor2}$ is not available globally

In [12]:
successor2 19 ;;
File "[12]", line 1, characters 0-10:
Error: Unbound value successor2
Hint: Did you mean successor?
   1: successor2 19 ;;

Defining and using functions with several parameters

In [14]:
let discriminant (a : int) (b : int) (c : int):int =  b * b - 4 * a * c ;;

discriminant 2 3 4 ;;
Out[14]:
val discriminant : int -> int -> int -> int = <fun>
Out[14]:
- : int = -23
In [ ]: