Closures in F#

In my previous post about F#:

First steps in F#

I declared that there is no variable in the language, instead, we talk about identifiers. Why? Let’s explore the concept of closure, and how is used in F#.

According to Wikipedia article about closures in computer science:

a closure is a function that is evaluated in an environment containing one or more bound variables

But, what does this mean? To reveal its meaning, let’s assign a value to an identifier, using fsi.exe, the F# interactive interpreter:

MSR F# Interactive, (c) Microsoft Corporation, All Rights Reserved
F# Version, compiling for .NET Framework Version v2.0.50727

NOTE: See ‘fsi –help’ for flags
NOTE: Commands: #r <string>; reference (dynamically load) the given DLL.
NOTE: #I <string>; add the given search path for referenced DLLs.

NOTE: #use <string>; accept input from the given file.
NOTE: #load <string> …<string>;
NOTE: load the given file(s) as a compilation unit.
NOTE: #time;; toggle timing on/off.
NOTE: #types;; toggle display of types on/off.
NOTE: #quit;; exit.
NOTE: Visit the F# website at
NOTE: Bug reports to Enjoy!

> let x = 2;;

val x : int

Now, we have an identifier named x. We can show its value:

> x;;
val it : int = 2

A simple integer. Now, we cannot change its value: this identifier was carved in stone as an integer 2. Nothing in the human history could change its value. Is it true? Let’s define a function:

> let dup n = n * x;;

val dup : int -> int

This function dup takes an argument n and multiplies it by the value of identifier x. This identifier is a free “variable” in the function. During the evaluation of the function, x takes its value from the environment. Let’s try now:

> dup 3;;
val it : int = 6

The result was six, as expected. But now, let’s “change” the value of x:

> let x = 3;;

val x : int

> x;;
val it : int = 3

But this is the point to understand closures: this “x” is ANOTHER identifier, that it shadows the previous one. BUT, for the function dup, the identifier x is STILL the previous one. Let’s try again to invoke the function:

> dup 3;;
val it : int = 6

The dup still uses the original x!! That’s the closure in action. If we try:

> dup;;
val it : (int -> int) = <fun:clo@0>

Note the clo @ 0 : its the signature of the closure this function is using. It points to the original environment where the function was defined.

This feature implies that the behaviour of a function doesn’t change after its definition. Even the apparently “free variables” are bounded at definition time. All this is part of the solid fundations of functional programming, in general, and F#, in particular.

About closures and related concept, lambdas, these are the seminal papers:

The Original ‘Lambda Papers’ by Guy Steele and Gerald Sussman

You can learn a lot about Lisp, and closures/lambdas, visiting:

Closures + Lambda = The key to OOP in Lisp « Learning Lisp


I implemented some lambdas and closures, in my Lisp interpreter:

AjLisp: a Lisp interpreter in .NET

More C# related stuff about closures:

What’s In A Closure?
Fibonacci Numbers, Caching and Closures

Angel “Java” Lopez

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s