CMSC330

Functional Programming

Functional Programming

Currying
Closures
Tail Recursion

Currying

Currying

Recall Higher Order Functions


map (fun x -> x + 3) [1;2;3;4];;
          

Functions were treated like data and passed in

If funtions are data, we can also return them


let add3 x = x + 3 in
let sub3 x = x - 3 in 
let lst = [add3;sub3] in
match lst with 
[]->(fun x -> x * 3)
|h::_-> h;;
          

Recall anonymous syntactic sugar


let add3 x = x + 3;;
let add3 = (fun x -> x + 3);;
          

This works for multi-argument functions


let sum x y = x + y;;
let sum x = fun y -> x + y;;
let sum = fun x -> fun y -> x + y;;
          

This works for multi-argument functions


let sum x y = x + y;;
let sum x = fun y -> x + y;;
let sum = fun x -> fun y -> x + y;;
          

function now becomes: one input -> one output

Currying: process of converting a multi-argument function into a series of functions that each take one input

Currying: process of converting a multi-argument function into a series of functions that each take one input

Why?

  • Avoid Repetition/Reusability
  • Break Functions Down
  • Some languages or functions only accept functions that take in one argument
  • Avoid Repetition/Reusability

let concat x y = x ^ y;;
concat "Hello " "world";;
concat "Hello " "earth";;

concat "Bye " "world";;
concat "Bye " "earth";;

let hello = concat "Hello ";;
let bye = concat "Bye ";;
hello "world"
hello "earth"

bye "world"
bye "earth"
          

Break Functions Down


let f x y z = (x + y) * z);;
f 3 4 6;;
let add = f 3 in 
let mult = add 4 in 
mult 6;;
          

Ultimately called a partial application

Some languages or functions only functions that take in one argument


let f x = (fun y -> x + y);;
let g = map f [1;2;3;4;5];;
map (fun h -> h 5) g;;
          

Technically this works either way in OCaml

Currying built in to OCaml How?

Closures

Remember everything is data in memory


let add x y = x + y;;
add 3 4;;
(* x and y are "local variables" *)
(* stored in a stack frame *)
          

Slight Issue


let partial = add 3;;
          

Where is 3 stored?

Closure: a tuple of an environment and a function (f,env)

Environment: mapping from variables to values

Evaluated at creation and immutable


let z = 4;;
let add x y = x + y;;
let g = add z;;
let z = 5;;
g 1;;
          

Tail Recursion

Recall this fib function


(* fib.ml *)
let rec fib n = 
if n < 2 then 1 else (fib (n-1)) - (fib (n-2));;
          
  • imperfect compiler: too many stack frames
  • Not tail Recursive

Let's fix this


(* fib-1.ml *)
let rec fib n a b = 
if n = 0 then a else fib (n-1) (a+b) a;;
          

Let's fix this


(* fib-1.ml *)
let rec fib n a b = 
if n = 0 then a else fib (n-1) (a+b) a;;
          

Tail Position: the last thing computed before a function returns

Tail Recursion: Having the recursive call be in tail position

(Depends on the context: only at top level)