Today, more and more languages supports functions as first-class values. This means a function is just a value like any other. You can pass functions as arguments to functions, but you are also able to create functions and return them from functions.

Whenever this is done we have to think about the life-time of variables. Usually all variables are lexical scoped. Consider the following example.

1
2
3
let add10 y =
    let x = 10
    x + y
1
2
3
4
public static int Add10(int y) {
    var x = 10;
    return x + y;
}
1
2
3
4
sub add10($y) {
    my $x = 10;
    return $x + $y;
}
1
2
3
4
function add10(y) {
    const x = 10;
    return x + y;
}
1
2
3
4
(define (add10 y)
    (define x 10)
    (+ x y)
)

In the example the variable x is created only temporary when the function is being executed. Once the function is finished the variable x is freed from memory. But this can change when we return a function.

1
2
3
let add10 () =
    let x = 10
    fun y -> x + y

Everytime add10 is called a new function is created and returned.

1
2
3
4
5
let f = add10 ()
let g = add10 ()

let a = f 20 // 30
let b = g 20 // 30
1
2
3
4
public static Func<int,int> Add10() {
    var x = 10;
    return (int y) => x + y;
}

Everytime add10 is called a new function is created and returned.

1
2
3
4
5
var f = add10();
var g = add10();

var a = f(20); // 30
var b = g(20); // 30
1
2
3
4
sub add10() {
    my $x = 10;
    return sub($y) { $x + $y };
}

Everytime add10 is called a new function is created and returned.

1
2
3
4
5
my $f = add10();
my $g = add10();

my $a = $f->(20); # 30
my $b = $g->(20); # 30
1
2
3
4
function add10(x) {
    const x = 10;
    return y => x + y;
}

Everytime add10 is called a new function is created and returned.

1
2
3
4
5
const f = add10();
const g = add10();

const a = f(20); // 30
const b = g(20); // 30
1
2
3
4
(define (add10)
    (define x 10)
    (lambda (y) (+ x y))
)

Everytime add10 is called a new function is created and returned.

1
2
3
4
5
(define f (add10))
(define g (add10))

(define a (f 20)) ; 30
(define b (g 20)) ; 30

add10 returns a function instead of doing a calculation. Because the function that is returned still access the variable x it means the variable is still not freed from memory. In the cases above the new functions f and g have access to its own x variable. Both functions have there own copy of x that is not shared between them.

This seems not so useful because x is always 10. But we can change the example to be more useful.

1
2
let add x y = x + y
let add x   = fun y -> x + y

Both definitions of add are the same in F# because of currying. Because x is now passed as an argument it is now possible to create multiple different add functions where each function has access to its own different x.

1
2
3
4
5
let add1  = add 1
let add10 = add 10

let a = add1  10 // 11
let b = add10 10 // 20
1
2
3
public static Func<int,int> Add(int x) {
    return (int y) => x + y;
}

Because x is now passed as an argument it is now possible to create multiple different add functions where each function has access to its own different x.

1
2
3
4
5
var add1  = add(1);
var add10 = add(10);

var a = add1(10);  // 11
var b = add10(10); // 20
1
2
3
sub add($x) {
    return sub($y) { $x + $y };
}

Because x is now passed as an argument it is now possible to create multiple different add functions where each function has access to its own different x.

1
2
3
4
5
my $add1  = add(1);
my $add10 = add(10);

my $a = $add1->(10);  # 11
my $b = $add10->(10); # 20
1
2
3
function add(x) {
    return y => x + y;
}

Because x is now passed as an argument it is now possible to create multiple different add functions where each function has access to its own different x.

1
2
3
4
5
const add1  = add(1);
const add10 = add(10);

const a = add1(10);  // 11
const b = add10(10); // 20
1
2
3
(define (add x)
    (lambda (y) (+ x y))
)

Because x is now passed as an argument it is now possible to create multiple different add functions where each function has access to its own different x.

1
2
3
4
5
(define add1  (add 1))
(define add10 (add 10))

(define a (add1  10)) ; 11
(define b (add10 10)) ; 20
This style is related to currying. We do currying whenever we turn a function with multiple arguments into a series of one-argument functions. In F# we could turn the following function.
1
2
let add x y z =
    x + y + z

into a curried form by writing.

1
2
3
4
let add x =
    fun y ->
    fun z ->
        x + y + z

but in F# it’s not needed because all functions are curried by default. With both definitions you can write:

1
let add10 = add 4 6

add10 now accepts the missing argument z. Passing fewer arguments as needed to execute a function is called Partial Application. In C#, Perl, JavaScript and Racket you must do this kind of transformation explicitly.

1
2
3
4
5
6
7
public static Func<int,Func<int,int>> Add(int x) {
    return (y) => {
        return (z) => {
            return x + y + z;
        };
    };
}

used like this:

1
2
var add10 = Add(6)(4);    // Func<int,int>
var num   = Add(6)(4)(5); // 15
1
2
3
4
5
6
7
sub add($x) {
    return sub($y) {
        return sub($z) {
            return $x + $y + $z;
        }
    }
}

used like this:

1
2
my $add10 = add(6)->(4);    # sub
my $num   = add(6)->(4)(5); # 15
1
2
3
4
5
6
7
function add(x) {
    return function(y) {
        return function(z) {
            return x + y + z;
        }
    }
}

used like this:

1
2
const add10 = add(6)(4);    // function
const num   = add(6)(4)(5); // 15
1
2
3
4
5
6
7
(define (add x)
    (lambda (y)
        (lambda (z)
            (+ x y z)
        )
    )
)

used like this:

1
2
(define add10 ((add 6) 4))    ; lambda
(define num   ((add 6) 4) 5)) ; 15
1
let add x y z = x + y + z

used like this.

1
2
3
let add10 = add 6 4         // int -> int
let numa  = add 6 4 5       // 15
let numb  = (((add 6) 4) 5) // 15

This is the reason why F# doesn’t use parenthesis for the arguments and they are also not required like in Racket (or another LISP-like language).

While being more usefull I guess you will still wonder why you ever want to do this kind of transformation. So here comes a more advanced example.

Consider we want to create a range function accepting a start and stop value. But instead of returning a List/Array or other kind of data, we want to return a function instead. Whenever this function is called it returns the next value starting with start upto stop.

This concept is also called an iterator and we can implement it easily with just a closure.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
// range : int -> int -> (unit -> option<int>)
let range start stop =
    // this is the state
    let mutable current = start
    // A function is returned and has has access to its
    // own unique mutable current variable.
    fun () ->
        if current <= stop then
            let tmp = current
            current <- current + 1
            Some tmp
        else
            None
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
public delegate int? RangeDelegate();
public static RangeDelegate Range(int start, int stop) {
    // This is the state
    int? current = start;
    // A function is returned and has has access to its
    // own unique mutable current variable.
    return () => {
        if ( current <= stop ) {
            return current++;
        }
        return null;
    };
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
sub range($start, $stop) {
    # This is the state
    my $current = $start;
    # A function is returned and has has access to its
    # own unique mutable current variable.
    return sub {
        if ( $current <= $stop ) {
            return $current++;
        }
        else {
            return;
        }
    }
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
function range(start, stop) {
    // This is the state
    let current = start;
    // A function is returned and has has access to its
    // own unique mutable current variable.
    return function() {
        if ( current <= stop ) {
            return current++;
        }
        else {
            return;
        }
    };
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
(define (range start stop)
    ; This is the state
    (define current start)
    ; A function is returned and has has access to its
    ; own unique mutable current variable.
    (lambda ()
        (cond
            [(<= current stop)
                (define tmp current)
                (set! current (add1 current))
                tmp
            ]
            [else #f]
        )
    )
)

The range function defines current and uses start as the initial value. Every function created by range has its own copy of current. So whenever we call the function that is returned by range, it just iterates from start to stop.

First we create a helper function to iterate through an iterator. This way we don’t need to write the logic for iteration every single time. Even if the code is short for iteration we can easily make mistakes.

1
2
3
4
5
6
7
let rec iter f i =
    match i() with
    | Some value ->
        f value
        iter f i
    | None ->
        ()

It is now easy to create multiple iterators and iterate through them.

1
2
3
4
5
let a = range  1 10
let b = range 20 80

a |> iter (fun x -> printfn "%d" x) // prints 1 to 10
b |> iter (fun x -> printfn "%d" x) // prints 20 to 80
1
2
3
4
5
6
7
8
public delegate int? RangeDelegate();
public static void Iter(RangeDelegate i, Action<int> f) {
    var x = i();
    while ( x != null ) {
        f(x.Value);
        x = i();
    }
}

It is now easy to create multiple iterators and iterate through them.

1
2
3
4
5
var a = Range( 1,10);
var b = Range(20,80);

Iter(a, x => Console.WriteLine(x)); // prints 1 to 10
Iter(b, x => Console.WriteLine(x)); // prints 20 to 80
1
2
3
4
5
6
sub iter($iter, $f) {
    while ( defined(my $x = $iter->()) ) {
        $f->($x);
    }
    return;
}

It is now easy to create multiple iterators and iterate through them.

1
2
3
4
5
my $a = range( 1, 10);
my $b = range(20, 80);

iter($a, sub($x) { say $x }); # prints 1 to 10
iter($b, sub($x) { say $x }); # prints 20 to 80
1
2
3
4
5
6
7
function iter(i, f) {
    let x = i();
    while ( x !== undefined ) {
        f(x);
        x = i();
    }
}

It is now easy to create multiple iterators and iterate through them.

1
2
3
4
5
const a = range( 1,10);
const b = range(20,80);

iter(a, x => console.log(x)); // prints 1 to 10
iter(b, x => console.log(x)); // prints 20 to 80
1
2
3
4
5
6
(define (iter i f)
    (define x (i))
    (cond
        [x (f x) (iter i f)]
    )
)

It is now easy to create multiple iterators and iterate through them.

1
2
3
4
5
(define a (range  1 10))
(define b (range 20 80))

(iter a (lambda (x) (displayln x))) ; prints 1 to 10
(iter b (lambda (x) (displayln x))) ; prints 20 to 80

Closures are tied to functional programming. But let’s assume you have an object-oriented language and want to achieve the same (without using its functional features). How do closures translate to object-oriented programming?

Answer: They are just classes with fields. A closure is the same as an object that contains data with a single method you can call.

This is how you implement add10.

1
2
3
4
5
type Add10() =
    let mutable x = 10

    member this.Call y =
        x + y

Like in the closure example it is now possible to create f and g and both objects will have its own x field.

1
2
3
4
5
let f = new Add10()
let g = Add10()    // new is optional

let a = f.Call(20) // 30
let b = g.Call(20) // 30
1
2
3
4
5
6
7
8
9
public class Add10 {
    private int x;
    public Add10() {
        this.x = 10;
    }
    public int Call(int y) {
        return this.x + y;
    }
}

Like in the closure example it is now possible to create f and g and both objects will have its own x field.

1
2
3
4
5
var f = new Add10();
var g = new Add10();

var a = f.Call(20); // 30
var b = f.Call(20); // 30
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
package Add10;
use v5.36;

sub new($class) {
    bless {
        x => 10,
    }, $class;
}

sub call($self, $y) {
    return $self->{x} + $y;
}

Like in the closure example it is now possible to create f and g and both objects will have its own x field.

1
2
3
4
5
my $f = Add10->new;
my $g = Add10->new;

my $a = $f->call(20); # 30
my $b = $g->call(20); # 30
1
2
3
4
5
6
7
8
function Add10() {
    this.x = 10;
}

// I am using invoke because JavaScript already has a global call method
Add10.prototype.invoke = function(y) {
    return this.x + y;
}

Like in the closure example it is now possible to create f and g and both objects will have its own x field.

1
2
3
4
5
const f = new Add10();
const g = new Add10();

const a = f.invoke();
const b = f.invoke();
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
(define Add10%
  (class object%
    (super-new)
    (field [x 10])

    (define/public (call y)
      (+ x y)
    )
  )
)

Like in the closure example it is now possible to create f and g and both objects will have its own x field.

1
2
3
4
5
(define f (new Add10%))
(define g (new Add10%))

(define a (send f call 20))
(define b (send f call 20))

Like in the example with the closure it seems useless to have x as a field, but we can make it configurable by passing it to the constructor. This would be add.

1
2
3
4
5
type Add(x) =
    let mutable x = x

    member this.Call y =
        x + y

It doesn’t really matter how that one-method is named. Use Run, Execute, Invoke, Call or any other synonyms for saying function.

1
2
3
4
5
let add1  = Add(1);
let add10 = Add(10);

let a = add1.Call(10);  // 11
let b = add10.Call(10); // 20
1
2
3
4
5
6
7
8
9
public class Add {
    private int x;
    public Add(int x) {
        this.x = x;
    }
    public Call(int y) {
        return this.x + y;
    }
}

It doesn’t really matter how that one-method is named. Use Run, Execute, Invoke, Call or any other synonyms for saying function.

1
2
3
4
5
var add1  = new Add(1);
var add10 = new Add(10);

var a = add1.Call(10);  // 11
var b = add10.Call(10); // 20
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
package Add;
use v5.36;

sub new($class, $x) {
    return bless { x => $x }, $class;
}

sub call($self, $y) {
    return $self->{x} + $y;
}

It doesn’t really matter how that one-method is named. Use Run, Execute, Invoke, Call or any other synonyms for saying function.

1
2
3
4
5
my $add1  = Add->new(1);
my $add10 = Add->new(10);

my $a = $add1->call(10);  # 11
my $b = $add10->call(10); # 20
1
2
3
4
5
6
7
8
function Add(x) {
    this.x = x;
}

// I am using invoke because JavaScript already has a global call method
Add.prototype.invoke = function(y) {
    return this.x + y;
}

It doesn’t really matter how that one-method is named. Use Run, Execute, Invoke, Call or any other synonyms for saying function.

1
2
3
4
5
var add1  = new Add(1);
var add10 = new Add(10);

var a = add1.invoke(10);  // 11
var b = add10.invoke(10); // 20
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
(define Add%
  (class object%
    (super-new)
    (init-field x)

    (define/public (call y)
      (+ x y)
    )
  )
)

It doesn’t really matter how that one-method is named. Use Run, Execute, Invoke, Call or any other synonyms for saying function.

1
2
3
4
5
(define add1  (new Add% [x 1]))
(define add10 (new Add% [x 10]))

(define a (send add1  call 10)) ; 11
(define b (send add10 call 10)) ; 20

This would be the iterator range.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
type Range(start, stop, ?current) =
    let mutable current = defaultArg current start

    // only get Properties
    member val Start   = start
    member val Stop    = stop
    member val Current = current

    member this.Next () =
        if current <= stop then
            let tmp = current
            current <- current + 1
            Some tmp
        else
            None

    member this.Iter f =
        let mutable x = this.Next ()
        while Option.isSome x do
            f (x.Value)
            x <- this.Next ()

In the object-oriented code I make the iter function a method. The properties are not really needed but still shown for comparison. Like mentioned in the C# version it is possible to use an interface and extension methods. I also could have used a Range module and use functions again, but then the current field had to be public. I also could have created a record with a module instead but here I wanted to show a class.

Now it becomes easy to define multiple ranges and iterate through them.

1
2
3
4
5
let a = Range(1, 5)
let b = Range(6,10)

a.Iter(fun x -> printfn "%d" x)
b.Iter(fun x -> printfn "%d" x)
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
public class Range {
    public int  Start   { get; }
    public int  Stop    { get; }
    public int? Current { get; set; }

    public Range(int start, int stop, int? current = null) {
        this.Start   = start;
        this.Stop    = stop;
        this.Current = current.HasValue ? current : start;
    }

    public int? Next() {
        if ( this.Current <= this.Stop ) {
            return this.Current++;
        }
        return null;
    }

    public void Iter(Action<int> f) {
        var x = this.Next();
        while ( x.HasValue ) {
            f(x.Value);
            x = this.Next();
        }
    }
}

In the object-oriented code i make the iter function a method. But I also cold have used an interface for the Range class and create Extensions Methods for additional functions. This is how LINQ is implemented.

Now it becomes easy to define multiple ranges and iterate through them.

1
2
3
4
5
var a = new Range(1, 5);
var b = new Range(6,10);

a.Iter(x => Console.WriteLine(x));
b.Iter(x => Console.WriteLine(x));
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
package Range;
use v5.36;
use Moo;
use Types::Standard qw(Int);
use namespace::clean;

has 'start'   => ( is => 'ro', isa => Int, required => 1 );
has 'stop'    => ( is => 'ro', isa => Int, required => 1 );
has 'current' => ( is => 'rw', isa => Int, required => 0 );

sub BUILD($self, $args) {
    if ( not exists $args->{current} ) {
        $self->current($self->start);
    }
}

sub next($self) {
    if ( $self->current <= $self->stop ) {
        my $tmp = $self->current;
        $self->current($tmp+1);
        return $tmp;
    }
    return;
}

sub iter($self, $f) {
    while ( defined(my $x = $self->next) ) {
        $f->($x);
    }
    return;
}

In the object-oriented code i make the iter function a method. Now it becomes easy to define multiple ranges and iterate through them.

1
2
3
4
5
my $r1 = Range->new(start => 1, stop =>  5);
my $r2 = Range->new(start => 6, stop => 10);

$r1->iter(sub ($x) { say $x });
$r2->iter(sub ($x) { say $x });
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
function Range(start, stop, current) {
    this.start   = start;
    this.stop    = stop;
    this.current = current === undefined ? start : current;
}

Range.prototype.next = function() {
    if ( this.current <= this.stop ) {
        return this.current++;
    }
    return;
}

Range.prototype.iter = function(f) {
    let x = this.next();
    while ( x !== undefined ) {
        f(x);
        x = this.next();
    }
}

In the object-oriented code i make the iter function a method. Now it becomes easy to define multiple ranges and iterate through them.

1
2
3
4
5
let a = new Range(1, 5);
let b = new Range(6,10);

a.iter(x => console.log(x));
b.iter(x => console.log(x));
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
(define Range%
  (class object%
    (super-new)
    (init-field start stop)
    (field [current start])

    (define/public (next)
      (cond
        [(<= current stop)
         (define tmp current)
         (set! current (add1 current))
         tmp]
        [else #f]
      )
    )

    (define/public (iter f)
      (define x (send this next))
      (cond
        [x (f x) (send this iter f)]
      )
    )
  )
)

In the object-oriented code i make the iter function a method. Now it becomes easy to define multiple ranges and iterate through them.

1
2
3
4
5
(define a (new Range% [start 1] [stop  5]))
(define b (new Range% [start 6] [stop 10]))

(send a iter (lambda (x) (displayln x)))
(send b iter (lambda (x) (displayln x)))