I’ve spent an hour reading many posts on this site and others about lambdas and closures. I think I understand what they are, i.e. how they work, but I do not understand why they exist. Many examples I see refer vaguely to their “power,” but in each of those cases I can think of a much simpler way to accomplish what is being illustrated. Maybe this is due to the examples being intentionally overly simple (for ease of understanding), or maybe I’m dense. But what I’d really like is to see a clear example of something you can accomplish with a closure or lambda that you can’t accomplish without one. Maybe this is a loaded question, since all programming paradigms eventually boil down to the same machine instructions, and anything that can be done in one language can be done in another, somehow. So I guess what I’m really asking is for an example of something done with a closure that is more elegant than when done without (which does not seem to be the case for any example I’ve seen yet).
Here’s what I’m talking about.
The leading answer for What is a 'Closure'? , an example in Scheme:
(define (make-counter)
(let ((count 0))
(lambda ()
(set! count (+ count 1))
count)))
(define x (make-counter))
(x) returns 1
(x) returns 2
...etc...
I don’t know Scheme really, but I think I see what’s going on. However, wouldn’t this be more straightforward and accomplish the same thing? Pseudocode:
function incrementCount(var counter) {
counter++;
return counter;
}
counter = 1;
counter = incrementCount(counter);
counter = incrementCount(counter);
Here’s another one on lambdas: What is a lambda (function)?
The JavaScript example given:
var adder = function (x) {
return function (y) {
return x + y;
};
};
add5 = adder(5);
add5(1) == 6
Again, why do it that way? Why not just say:
function adder(x, y) {
return x + y;
}
adder(5, 1);
Every example I’ve seen seems like an overly complicated way to do something that can easily be done with basic functions. These examples certainly don’t illustrate any amazing cool “power” that I can see. So please, somebody enlighten me, I must be missing out on something. Thanks.
Lambda calculus is actually pretty simple, and not that useful on its own. However it is when you start learning the implications of lambda calculus and strategies of application control using functional design patterns that you will become a better and more powerful programmer.
The premise is that functions are also values and this makes it really powerful for abstracting many concepts. Your two examples show the simplest way that closures and currying are implemented. Those are trivial examples. When you begin to program using a functional style, those pattern will come up over and over again as very powerful ways to abstract away complexity.
seperation of concerns
Functional programming is useful is when you start abstracting using higher order functions, the typical example being – I want to do something to a collection of objects.
so in an imperative program, you use a for loop:
notice that in the block of code, the
dosomethingfunction is right in the middle of the for loop. You can’t really separate out what you are doing to each element of the array from the actual for-loop control structure.However, by using a functional style, the control structure of the loop is abstracted away using
map– a higher order function – you get clear separation of two concepts of looping and function application. This is the equivalent code in scheme.maptakes care of the fact that you are traversing each element of the array.dosomethingtakes care of the fact that you are performing an operation on each element of the array. Reasoning about this becomes much more clear and changing the code becomes much easier. Now imagine that everyforloop in your code was replaced by this construct and how many lines of code it will save.cheap constructors
Addressing the concept of closures and currying. There is an equivalence between objects and functions. Essentially, functions can be made to look and behave like objects. Javascript makes great use of this fact. Anything you can do with objects, you can also do with functions. In fact, by getting rid of the distinction between what an object is and what a function is, you have effectively decluttered your mind and have one way of thinking about the problem – that is, through code that is built up through functionality.
I am using clojure code here because it is what i’m comfortable with:
This is the clojure code for trivial adder example, With the adder example, you are calling a
addnwith the number 5 to get back function that adds 5 to a number. a general use case may be:Say you had a function
download-and-save-tothat takes a url and a database, saves the url to a database table and returns true when it is successful, you can do exactly the same abstraction as you did with+:Notice that the structure is equivalent even though you are doing vastly different things. Think about how you would have approach this problem using java or c++. There would be a lot more code involved in class definitions, factory methods, class abstractions, inheritence…. essentially. you have to go through a whole lot more ceremony to get the same effect.
opening your mind
Because of the way you can express ideas so succinctly, functional programming can let you grasp many concepts that are very difficult to express in more verbose languages. The tool you pick will make exploring certain problems easier or harder.
I highly recommend clojure – (http://www.4clojure.com/) and lighttable – (http://www.lighttable.com/, http://www.kickstarter.com/projects/ibdknox/light-table) to get started. From my personal experience, my one year of learning and exploring concepts by the clojure community was akin to about 10 years of learning java, c++ and python combined.
Oh, did I mention how much fun I’m having learning all this stuff? Monads, combinators, propagators, continuations… all those scary looking academic concepts are actually well within reach when you have the right tools for understanding them.