Closures in F#

F# supports anonymous functions, which can form closures. Anonymous functions are useful when you want to define a function inline without having to name it.

open System

// This function 'intSeq' returns another function, which
// we define anonymously in the body of 'intSeq'. The
// returned function closes over the variable 'i' to
// form a closure.
let intSeq () =
    let mutable i = 0
    fun () ->
        i <- i + 1
        i

// We call 'intSeq', assigning the result (a function)
// to 'nextInt'. This function value captures its
// own 'i' value, which will be updated each time
// we call 'nextInt'.
let nextInt = intSeq()

// See the effect of the closure by calling 'nextInt'
// a few times.
printfn "%d" (nextInt())
printfn "%d" (nextInt())
printfn "%d" (nextInt())

// To confirm that the state is unique to that
// particular function, create and test a new one.
let newInts = intSeq()
printfn "%d" (newInts())

To run the program, save it as Closures.fs and use the F# compiler (fsc) to compile it, then run the resulting executable:

$ fsharpc Closures.fs
$ mono Closures.exe
1
2
3
1

In F#, closures work similarly to other functional programming languages. The intSeq function returns an anonymous function that increments and returns a mutable variable i. Each time this anonymous function is called, it increments its own private copy of i.

The nextInt and newInts variables are bound to separate instances of this anonymous function, each with its own state. This demonstrates how closures in F# can maintain state between function calls.

The last feature of functions we’ll look at for now is recursion.