views:

189

answers:

4

For some reason, I tend to associate closures with functional languages. I believe this is mostly because the discussions I've seen concerning closures is almost always in an environment that is focused around functional programming. That being said, the actual practical uses of closures that I can think are are all non-functional in nature.

Are there practical uses of closures in functional languages, or is the association in my mind mostly because closures are used to program in a style that's also common to functional programming languages (first class functions, currying, etc)?

Edit: I should clarify that I refering to actual functional languages, meaning I was looking for uses that preserve referential transparency (for the same input you get the same output).

Edit: Adding a summary of what's been posted so far:

  1. Closures are used to implement partial evaluation. Specifically, for a function that takes two arguments, it can be called with one argument which results in it returning a function that takes one argument. Generally, the method by which this second function "stores" the first value passed into it is a closure.
  2. Objects can be implemented using closures. A function is returned that has closes around a number of variables, and can then use them like object attributes. The function itself may return more methods, which act as object methods, which also have access to these variables. Assuming the variables aren't modified, referential transparency is maintained.
+3  A: 

One nice use for closures is building things like decision trees. You return a classify() function that tests whether to go down the left or right tree, and then calls either its leftClassify() or rightClassify() function depending on the input data. The leaf functions simply return a class label. I've actually implemented decision trees in Python and D this way before.

dsimcha
Am I understanding correctly that what the closure is being used for here is pretty much to create an object with a single method. If the tree of data itself is static, then classify is a pure function? That makes sense.
RHSeeger
Right. You build the right and left subtrees using recursion. It could also be done with objects, but closures are often more syntactically convenient.
dsimcha
I'm selecting this post as the answer because it does a good job of presenting 1 of the 2 ways mentioned to use closures functionally. That being said, I voted of the 3 answers that originally provided information (or related samples) about those ways.
RHSeeger
+6  A: 

I use lots of closures in Javascript code (which is a pretty functional language -- I joke that it is Scheme with C clothing). They provide encapsulation of data that is private to a function.

The most ubiquitous example:

var generateId = function() {
    var id = 0;
    return function() {
        return id++;
    }
}();
window.alert(generateId());
window.alert(generateId());

But that's the hello, world of Javascript closures. However there are many more practical uses.

Recently, in my job, I needed to code a simple photo gallery with sliders. It does something like:

var slide = function() {
    var photoSize = ...
    var ... // lots of calculations of sizes, distances to scroll, etc
    var scroll = function(direction, amout) {
        // here we use some of the variables defined just above
        // (it will be returned, therefore it is a closure)
    };
    return {
        up: function() { scroll(1, photoSize); },
        down: function() { scroll(-1, photoSize); }
    }
}();

slide.up();
// actually the line above would have to be associated to some
// event handler to be useful

In this case I've used closures to hide all the up and down scrolling logic, and have a code which is very semantic: in Javascript, "slide up" you will write slide.up().

Bruno Reis
One remark: when I say "lots" I actually mean "frequently". You should not use **lots** of closures without knowing what you are doing, since they could eat up lots of memory.
Bruno Reis
This isn't really what I was looking for because the functions returned aren't pure (different outputs for the same inputs over time). That being said, the concept could be used in a purely functional way, much the way dsimcha describes. The code and sample usage help show what you're talking about well.
RHSeeger
+3  A: 

They're used for a lot of things. Take, for example, function composition:

let compose f g = fun x -> f (g x)

This returns a closure that uses the arguments from the function environment where it was created. Functional languages like OCaml and Haskell actually use closures implicitly all over the place. For example:

let flip f a b = f b a

Usually, this will be called as something like let minusOne = flip (-) 1 to create a function that will subtract 1 from its argument. This "partially applied" function is effectively the same as doing this:

let flip f a = fun b -> f b a

It returns a closure that remembers the two arguments you passed in and takes another argument of its own.

Chuck
In the case of flip, the first version is *much* more clear. I see only disadvantages on the second version, I would avoid it.
Bruno Reis
You'll have to forgive me, my understanding of Haskell is limited. Are you saying that currying/partial application (I get them confused) is a form of closure. That the function returned from the partial application remembers the already supplied inputs because it closes over them from the original call?
RHSeeger
Yes. How it is actually stored is an implementation detail, but conceptually, curried functions are a chain of closures. That's what I was trying to get at by showing `flip` — not that the second version is something you'd ever want to write, but that the first version is basically sugar for the second.
Chuck
BTW, the code in this post is OCaml/F# (valid in either language), in case anybody is trying to follow along.
Chuck
+1  A: 

Closures can be used to simulate objects that can respond to messages and maintain their own local state. Here is a simple counter object in Scheme:

;; counter.ss
;; A simple counter that can respond to the messages
;; 'next and 'reset.  

(define (create-counter start-from)
  (let ((value start-from))
    (lambda (message)
      (case message
    ((next) (set! value (add1 value)) value)
    ((reset) (set! value start-from))
    (else (error "Invalid message!"))))))

Sample usage:

> (load "counter.ss")
> (define count-from-5 (create-counter 5))
> (define count-from-0 (create-counter 0))
> (count-from-5 'next)
6
> (count-from-5 'next)
7
> (count-from-0 'next)
1
> (count-from-0 'next)
2
> (count-from-0 'reset)
> (count-from-0 'next)
1
Vijay Mathew