Programming – Is Every Function a Closure?

cclosuresjavascriptpythonterminology

Wikipedia says, that closure – is a function, which has an access to variables, declared outside of the function. There is even an example:

function startAt(x)
   function incrementBy(y)
       return x + y
   return incrementBy

variable closure1 = startAt(1)
variable closure2 = startAt(5)

But according to most programming languages (including python, javascript, swift, etc.) the next example is correct (written in python):

# Script starts
test = "check"

def func(test2):

    def func2():
        return test2 == test

    return func2()

print func("check") // returns TRUE
# Script ends

Basically, func is not a closure, but it obviously uses variable test, declared outside of the function. Does that mean func IS a closure?

Even in C++ you can run this:

std::string test = "check";

bool func(std::string test2) {
    if (test2 == test)
        return true;
    else
        return false;
}

int main() {
    if (func("check"))
        std::cout << "TRUE" << std::endl; // prints TRUE
}

Eventually, this makes every function being a closure. Where am I wrong?

Best Answer

No, not every function is a closure.

Wikipedia says:

... closure ... is a function or reference to a function together with a referencing environment — a table storing a reference to each of the non-local variables (also called free variables or upvalues) of that function.

I'd add "non-local and non-global", but the idea is correct.


Neither your C++ nor Python examples use closures. In both cases it's just scoping rules allow functions to see their outer scope and global scope.


"Closure" happens in the 1st example - incrementBy is constructed in and then returned from it's outer function, capturing argument x. When you assign variable closure1 = startAt(1), you end up having a closure (function) inside closure1 var which captured argument, which value happened to be 1, so when you call closure1(2) the result is 3 (1 + 2).

Think of it as memorizing some information about closure's declaration scope: incrementBy retain a memory about insides of startAt, specifically a value of it's argument x.

In lambda calculus, as I know, those "non-local" variables are called "free", and functions with free variables are called "open terms". Closure is a process of "closing" open terms by "fixing" values of those free variables in aforementioned "environment table". Hence the name.


It's worth noting that in Python and JS closure happens implicitly, while in PHP you have to explicitly tell which variables you want to close over (capture): http://php.net/manual/en/functions.anonymous.php - note use keyword in declarations:

// equivalent to the 1st example
function startAt($x) { //        vvvvvvvv          vv
    $incrementBy = function ($y) use ($x) { return $x + $y };
    return $incrementBy;
}
Related Topic