29

I'm trying to understand closures, but literally every definition of a closure that I can find uses the same cryptic and vague phrase: "closes over".

What's a closure? "Oh, it's a function that closes over another function."

But nowhere can I find a definition of what "closes over" means. Can someone explain what it means for Thing A to "close over" Thing B?

smeeb
  • 27,777
  • 57
  • 250
  • 447
  • http://en.wikipedia.org/wiki/Closure_%28computer_programming%29#History_and_etymology - gives you something to start with. A closure "closes" open bindings. – Blorgbeard Jun 08 '15 at 01:14
  • 3
    LOL, "*A closure is something that closes over open bindings.*" Could that be any less descriptive?!? Really?!? **Really?!?!** – smeeb Jun 08 '15 at 01:57
  • Well you'd have a point if that was a direct quote from anything I said or linked. Here is what I linked to: "a lambda expression whose open bindings (free variables) have been closed by (or bound in) the lexical environment, resulting in a closed expression, or closure". – Blorgbeard Jun 08 '15 at 02:04
  • 1
    The word "closed" here derives from mathematical logic... The relevant concepts are "expression", "free variable", "bound variable", and "closed term". See e.g. http://en.wikipedia.org/wiki/Free_variables_and_bound_variables – Nemo Jun 08 '15 at 02:28

2 Answers2

14

A closure is a pair consisting of a code pointer and an environment pointer. The environment pointer contains all of the free variables of a given function. For example:

fun f(a, b) = 
  let fun g(c, d) = a + b + c + d
  in g end

val g = f(1, 2)
val result = g(3, 4)  (*should be 10*)

The function g contains two free variables: a and b. If you are not familiar with the term free variable, it is a variable that is not defined within the scope of a function. In this context, to close over something, means to remove any occurrences of a free variable from a function. The above example provides good motivation for closures. When the function f returns, we need to be able to remember what the values of a and b are for later. The way this is compiled, is to treat function g as a code pointer and a record containing all the free variables, such as:

 fun g(c, d, env) = env.a + env.b + c + d
 fun f(a, b, env) = (g, {a = a, b = b})
 val (g, gEnv) = f(1, 2)
 val result = g(3, 4, gEnv)

When we apply the function g, we supply the environment that was returned when calling function f. Note that now function g no longer has any occurrences of a variable that is not defined in its scope. We typically call a term that doesn't have any free variables as closed. If you are still unclear, Matt Might has an excellent in depth explanation of closure conversion at http://matt.might.net/articles/closure-conversion/

Same example in Javascript

Before closure conversion

function f(a, b){
    function g(c, d) {
        return a + b + c + d
    }
    return g
}

var g = f(1, 2)
var result = g(3, 4)

After closure conversion:

function g(c, d, env) {
    return env.a + env.b + c + d
}

function f(a, b, env) {
    return [g, {"a": a, "b": b}]
}

var [g, gEnv] = f(1, 2)
var result = g(3, 4, gEnv)
Matt
  • 4,029
  • 3
  • 20
  • 37
  • Shouldn't it be : _The function `g` contains two free variables: `a` and `b`._ ? You said just after that a free variable is one which __wasn't__ defined in the scope ? – Sehnsucht Jun 08 '15 at 07:38
  • Yes, sorry that was a typo. Thanks! – Matt Jun 08 '15 at 12:47
  • @NatalieCardot, Inside the body of function `g`, arguments `a` and `b` are neither passed in as arguments nor defined locally. That fits Udacity's definition quite well. – Matt Jun 19 '18 at 18:10
  • The explanation is good, but the example is confusing me. I don't know what programming language is being used, is it possible to add similar code examples using JavaScript? `fun f(a, b, env) = (g, {a = a, b = b})` in particular, makes no sense to me and is the most confusing. Having a JS equivalent would help ease the language's specifics and make that answer accessible to more people. – Vadorequest May 20 '21 at 11:36
  • In the JS snippet “Before closure conversion”, I would say that the function `g` closes over the variables `a` and `b`. This usage is consistent with the one in [How do JavaScript closures work?](/a/111111/4642212). Is this answer saying that nothing is being closed over in the snippet “Before closure conversion”, but something _is_ in the snippet “After closure conversion”? Could this please be clarified? – Sebastian Simon Oct 30 '22 at 11:36
  • Running the Javascript code step by step on [pythontutor](https://pythontutor.com/) convince me how the code works. – Mohammad Reza Khahani Aug 04 '23 at 06:38
8

From apple documentation

Closures are self-contained blocks of functionality that can be passed around and used in your code. Closures in Swift are similar to blocks in C and Objective-C and to lambdas in other programming languages.

But what that means?

It means that a closure captures the variables and constants of the context in which it is defined, referred to as closing over those variables and constants.

I hope that helps!

Community
  • 1
  • 1
Icaro
  • 14,585
  • 6
  • 60
  • 75
  • Could I say "A closure is a function that has no free variable"? Or is it incorrect? From what I gather from your answer, it might be a good definition. – Vadorequest May 20 '21 at 11:38
  • 1
    @Vadorequest I would say a _closed function_ is a function with no free variables. A _closure_ is a function with free variables, that has been given an environment outside the function where those free variables are bound to values, resulting in the function becoming closed over those variables. – MetaEd May 21 '21 at 22:45
  • Thank you! Reading http://matt.might.net/articles/closure-conversion/ also kinda helped me understand that better. – Vadorequest May 22 '21 at 10:30