

Understand closures - christian_fei
http://christian-fei.com/understand-closures/

======
mdkess
I don't think that I really understood closures until I took Dan Grossman's
Coursera course "Programming Languages." In it, we implemented in Racket a
simple programming language which included closures, which is the point where
it really clicked for me.

In the class, he defines a closure as follows:

"We have said that functions are values, but we have not been precise about
what that value exactly is. We now explain that a function value has two
parts, the code for the function (obviously) and the environment that was
current when we created the function. These two parts really do form a “pair”
but we put “pair” in quotation marks because it is not an ML pair, just
something with two parts. You cannot access the parts of the “pair”
separately; all you can do is call the function. This call uses both parts
because it evaluates the code part using the environment part.

This “pair” is called a function closure or just closure. The reason is that
while the code itself can have free variables (variables that are not bound
inside the code so they need to be bound by some outer environment), the
closure carries with it an environment that provides all these bindings. So
the closure overall is “closed” — it has everything it needs to produce a
function result given a function argument."

(section course notes:
[https://d396qusza40orc.cloudfront.net/proglang/lecture_slide...](https://d396qusza40orc.cloudfront.net/proglang/lecture_slides%2Fsection3%2Fsection3sum.pdf))

~~~
christian_fei
thanks for the notes!

~~~
mdkess
No problem, thanks for the blog post! I'd highly recommend taking the course -
even with a traditional math/cs undergraduate degree from a good school, it
was one of the best courses I've ever taken, both in terms of execution and
the amount that I learned from it.

~~~
christian_fei
awesome, will do!

------
RyanZAG
The approach Java takes to closures, for all its faults, makes it so much
easier to avoid this kind of accident without having to double check all your
closures every time.

Java only allows 'final' or immutable variables to be passed into closures.
This prevents the value from changing and ensures that the compiler catches
the problem if you try to pass a changing value into a closure.

~~~
christian_fei
I come exactly from this background at school, so I never had this 'problem'
with Java.

It was pretty new to me and kinda not sensed the concept behind closures.

I would like to know what you think about the explanation I provided in the
post about closures. Did I get the point? Don't hesitate to tell me if I'm
totally wrong

~~~
RyanZAG
Yes, spot on.

For your original code example, the Java compiler would have failed with an
error that the variable 'i' was not declared final (immutable). Java 8
supports lambdas now, but in earlier Java versions you would have had to add a
line like 'final int fi = i;' and you could then have used the fi inside the
closure. The point in my previous post that the compiler detecting this
ambiguity is exceptionally helpful and I'd prefer more languages to follow
that route.

With Java 8 lambdas, it's much the same but with some nice syntax to make it
easier[1].

[1] [http://java.amitph.com/2012/08/at-first-sight-with-
closures-...](http://java.amitph.com/2012/08/at-first-sight-with-closures-in-
java.html)

~~~
christian_fei
never got _that_ much into Java though

------
acjohnson55
Not to be a hater, but the examples on the blog post are insane. Why would I
write code like any of those?

To try to put a name on what you've observed, what you're really doing is
emulating a call-by-name [1] evaluation strategy, in which you want an
expression to be evaluated at the time the asynchronous callee needs the
value, rather than when the call is scheduled. Some languages (like Scala)
have specific syntax for this, but in other languages, you emulate this
behavior by wrapping the expression in a function, and calling that function
when you want the expression to be evaluated.

The closure facilitates this by letting you bind names in the expression to
variables in the outer scope. These variables aren't available to the actual
caller of the function (somewhere in setTimeout's implementation) to be bound
to the function's arguments in the "normal" way. So really, you find that
there are two basic ways to make variables available to a function's scope:
the invoker of the function can bind the function's arguments to values in its
scope, or the function can bind variables from any of the scopes that enclose
it, namely all of the enclosing functions. (There's also `this`, but that's
another story.)

A much better use case is if you want an event handler to have access to the
state of the object that registered it. If you bind the event handler within
that object's scope, you can refer to that state within the event handler, and
whenever it fires, the current value of state will available from the
enclosing scope. This comes up all the time for me when writing Backbone apps.
When doing this kind of stuff, be sure to understand thoroughly how
Javascript's `this` works (ugh...).

Also, when designing recursive algorithms, closures give the innermost nested
layers of your algorithm access to variables from outer scopes, reducing the
need to awkwardly pass in parameters that don't change between inner function
invocations.

Closures are just the tip of the iceberg. Other concepts like higher-order
functions, decorators, and combinators are also really powerful. I highly
recommend the most excellent Javascript Allongé [2] for anyone who truly wants
to understand this stuff, and learn how to really make it work for them.

[1]
[http://en.wikipedia.org/wiki/Evaluation_strategy#Call_by_nam...](http://en.wikipedia.org/wiki/Evaluation_strategy#Call_by_name)

[2] [https://leanpub.com/javascript-
allonge/read](https://leanpub.com/javascript-allonge/read)

~~~
christian_fei
I knew I would get some negative feedback, but that's the whole point of
having posted it here: to get feedback. I came across this problem and found a
_possible_ solution like closures worked fine. I was just trying to get my
head around closures, because that's the only thing that I found useful for
this particular use case. Anyways, thanks for your feedback, much appreciated!

------
btilly
Closures are simpler than that. All that a closure does is capture an
enclosing environment, and then be able to refer to variables from it later.

All of the confusion in JavaScript comes from the fact that the enclosing
environment is generally bound to the nearest function call. This is not what
people expect, and it is not what happens in other languages with closures.

If versioning JavaScript features was not such a mess, it wouldn't happen in
JavaScript either. Everyone would learn to declare variables with let instead
of var, and closures would just work sanely. Unfortunately you need to use
JavaScript 1.7 to get that feature, and browsers assume that you're using
JavaScript 1.5 unless you jump through hoops to get there.

See [https://developer.mozilla.org/en-
US/docs/Web/JavaScript/New_...](https://developer.mozilla.org/en-
US/docs/Web/JavaScript/New_in_JavaScript/1.7) for more.

~~~
christian_fei
i came to the conclusion that functions === closures.

closure/functions close the parents scoped variables in an own scope

~~~
btilly
That conclusion is language dependent. When you learn other languages, you'll
encounter ones like eLisp and C++ which have equivalents of anonymous
functions, without making them closures.

~~~
christian_fei
ok. but at least in javascript this mysterious phrase is true, right?

~~~
btilly
Yes.

But it is one of a set of mysterious phrases like "pass by value" and "pass by
reference" which, if you learn them, will make it much easier to keep multiple
languages in your head.

------
padolsey
I don't believe this is "the most practical explanation of closures out there"
as the author claims, but it does present a use-case. The most important thing
to grasp if you're fussed about naming concepts in JavaScript is the
difference between a function, a scope [1], a closure [2], and an IIFE [3].

[1]
[https://developer.mozilla.org/en/docs/Web/JavaScript/Referen...](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Functions_and_function_scope)

[2] [http://unscriptable.com/2011/10/02/closures-for-dummies-
or-w...](http://unscriptable.com/2011/10/02/closures-for-dummies-or-why-iife-
closure/)

[3] [http://benalman.com/news/2010/11/immediately-invoked-
functio...](http://benalman.com/news/2010/11/immediately-invoked-function-
expression/)

~~~
christian_fei
thank you, I'm really confused about naming concepts in JavaScript because one
time you read something, and a minute after on a stackoverflow thread you find
it explained and named differently. but I will read through the links you
posted, appreciate that

------
city41
"This works because functions create an own scope for the variable"

It works because it's a brand new variable. JavaScript is a pass by value
language, and the i inside the function is a different chunk of memory than
the i from the loop

~~~
christian_fei
updated. thanks for the clarification

------
reycharles
This might as well be titled "Understand mutable variables (and function-
scoping)".

The post doesn't really explain closures, and the examples really just show
what happens when you mutate variables, in this case in a for-loop - they
change value!

The last example also shows how javascript has function scope as opposed to
block scope, i.e. the variable "string" might as well have been declared
outside the for-loop.

~~~
christian_fei
What's wrong with mutable variables and closures? I 'seal' the variable value
'i' into a closure, isn't that a good example for a closure? I repeat, I wrote
this to get constructive feedback, so thanks, and I would like to discuss this
further

------
k3n
Decent short explanation. If anyone would like an exhaustive explanation, I'd
recommend comp.lang.javascript's FAQ[1].

It's overkill to if you just want a working definition, but is instrumental in
understanding the underlying concepts that power closures.

1\.
[http://jibbering.com/faq/notes/closures/](http://jibbering.com/faq/notes/closures/)

~~~
christian_fei
thank you, will read through the notes.

PS: can we say that functions === closures?

------
mdellabitta
The behavior of the "I don't believe you" buttons was only slightly annoying,
but then I made the mistake of clicking the "now i do" button, too. :)

~~~
christian_fei
lol

