Talk:Closure (computer programming)

This is an old revision of this page, as edited by Pi Delport (talk | contribs) at 21:06, 3 August 2006 (Don't start with Lisp: comment). The present address (URL) is a permanent link to this revision, which may differ significantly from the current revision.

Latest comment: 19 years ago by Piet Delport in topic Don't start with Lisp

Don't start with Lisp

I don't think the initial examples should be in Lisp. Here's why: the vast majority of Lisp programmer will already be familiar with closures, but a lot of people who navigate to this page will tend to be people who aren't familiar with Lisp (if they were familiar with Lisp, they'd probably know what a closure was already). I'd suggest (for the initial examples) some language which has syntax which is more C-like. Maybe javascript? Or maybe pseudocode. Of course, definitely include the Lisp code later. Just not the very first thing. Does anyone else agree?

This will probably be a controversial suggestion as Lisp advocates will argue that the language is directly rooted in lambda calculus. Still, I think it is a good idea. I would suggest using Eiffel for such intro examples because it's an imperative language, close to what most people use, and yet the syntax is very clear and the notion of agent directly represents the mathematical concept of closure. I am willing to do it but I will wait to see if there is some agreement. Necklace 22:56, 2 August 2006 (UTC)Reply
It's important to remember here that Wikipedia is not a textbook or tutorial, but an encyclopedia: the goal is not to teach, but to describe, with accuracy and relevance. When it comes to the choice of example language, it's not industrial popularity that's relevant, but things like historical prominence, and how well it's represented in the literature.
With all that in mind, i think Lisp is an ideal choice; probably the only change called for is to switch the examples to the Scheme dialect, because of its simpler syntax, and because of the important role it played in popularizing the concept of closures to begin with. (If a non-Lispy example is desired for contrast, a member of the ML family is probably appropriate.) --Piet Delport 21:06, 3 August 2006 (UTC)Reply

Closures in Perl

In perl at least, a closure doesn't have to be a function definition. It's more or less anything between a pair of braces, that serves as it's own variable scope. In Damian Conway's Object Oriented Perl, I believe he uses closures to implement the private variables of an object, so it might be misleading to say that the closure itself is an object or acts like one. In any case, something needs to be said about scope here. Wesley

How could one use a closure that's not a function definition?

This isn't right. In perl6 blocks will technically be closures, but thats pretty obscure stuff afaik. In perl5 blocks aren't closures. Demerphq 19:09, 7 April 2006 (UTC)Reply

Regarding the "acts as an object" comment, I was thinking of a closure like this:

sub counter {
    my $x = shift;
    return sub { print "$x\n"; $x--; };
}

$h = counter(4);
$g = counter(7);

$h->();  # gives 4
$h->();  # gives 3
$g->();  # gives 7
$h->();  # gives 2
AxelBoldt

A closure can be used as a way to simulate static variables. For instance consider the following (slow) function:

sub fib {
  my $n = shift;
  if ($n <= 1) {
    return 1;
  }
  else {
    return fib($n-1) + fib($n-2);
  }
}

It works, but calculating (say) fib(40) may take a while. Now let's add a private closure in which we cache results (this kind of caching is known as memoizing):

{
  my %cache;
  sub fib {
    my $n = shift;
    if ($n <= 1) {
      return 1;
    }
    elsif (exists $cache{$n}) {
      return $cache{$n};
    }
    else {
      return $cache{$n} = fib($n-1) + fib($n-2);
    }
  }
}

Now the function runs much more quickly. If we had static variables (the "my $foo if 0;" bug does not count in my books!), that would be the right way to do this, but closures can do it as well.

BTW I hope that the example I gave is not too complex. I wanted to provide something that was accessible but gave an idea of why someone might choose to use closures.

bjt


IMO the example was too complex. Also, Perl is a heinous language for explaining computer science concepts (e.g., you have to use "shift" to peel off arguments --- utterly obscure --- not to mention all the other random syntactic noise that comes with Perl). I replaced it with a more basic explanation that just conveys the idea of lexical scope capture. I used ML, which has a far more concise and pseudocode-like syntax than Perl.

If you want to do a more involved programming example, IMO you should create an article for first-class function or higher-order function and write it there; or, better still add it to functional programming. The term "closure", as commonly used by language designers/implementors, refers specifically to the data structure with the code pointer and environment pointer. Programming using higher-order functions is a broader idea, and belongs in a broader article. k.lee 00:44, 24 Oct 2003 (UTC)


Re: typical implementation as "a set of values that record the values of the relevant variables in the function's lexical environment at the time of binding", this was not correct. A naive Lisp interpreter can implement a closure as a pair containing a pointer to the function and a pointer to the actual lexical environment (activation record) at the point of capture. There's no recording of values, or selection of relevant variables for capture. Wasteful and slow, but adequate. k.lee 17:27, 24 Oct 2003 (UTC)


IMO a Perl example is well called for. The counter example IMO isn't bad. I took the liberty of updating it a touch style wise tho, the &$f() style is a bit archaic. And really I think there are a lot more people out there that can read Perl than can read ML, and k.lee's comments appear a bit uninformed, shift isnt the only way to access arguments in perl. Also, Perl is one of the few "popular" (non-academic maybe is better) languages that makes heavy use of closures, so i think an example of it would be well worth while. Demerphq 19:09, 7 April 2006 (UTC)Reply


Im going to add a perl example back to the page unless somebody protests. Demerphq 17:05, 10 April 2006 (UTC)Reply

Closures and Java

I have just edited the page such that the Java simulation section has "final" instead of "immutable". My understanding of the term immutable in the context of Java is that it means once you have a reference to the object its internal state will never change i.e. all fields (including private ones) can be declared final and all references that the object holds are themselves to immutable objects. This property, as far as I know, is not detected or enforced by the runtime and is not necessary for a local variable to be used in an anonymous inner class. The meaning of the keyword final, on the other hand, is that the value of the variable will never change which object it references (or will never change value if a primitive). It is this that is necessary for the anonymous inner type to make use of the variable so that the runtime can simply clone the primitive values and object references of final variables on the stack when instantiating the anonymous inner class.

--Jwal 18:35, 12 Jun 2004 (UTC)



Closures and Python

Why Python doesn't have closures:

Python has nested scope, but not the ability to modify variables in outer lexical scopes (except for globals, and via reflexion). Therefore, Python doesn't have closures. It's that simple. --Lament

Admittedly Python closures are broken in this respect compared to Scheme, but this is overstated. As a matter of practice, 99% of the time Python closures work just like Scheme closures. They look the same, work the same, and are used for the same purposes. On the other hand, if you're using a closure in Python to hide modifiable state, it's probably a kindness that Python doesn't support what you want to do. Jorend 20:41, 10 January 2006 (UTC)Reply
I have changed my view on this. Python closures are not used for the same purposes as Scheme closures. I am told that in Scheme, closures are very commonly used to hide state. In Python, you would just use a class instead. Jorend 21:50, 15 February 2006 (UTC)Reply

FWIW, Python does allow you to modify variables in outer scopes; it does not, however, have syntax for rebinding names in outer scopes to new values. The workaround when this is needed (which isn't often) is to use a mutable container object in the enclosing scope, and replace the contained value rather than the container

>>> def foo(start=0):
...     counter = [start] # counter is 1-element array
...     def bar():
...         counter[0] = counter[0] + 1
...         return counter[0]
...     return bar
...
>>> count = foo(10)
>>> print count()
11
>>> print count()
12
>>> print count()
13

Although Jorend is right that classes are preferred for encapsulation in Python, closures actually hide state better than classes do. All class data is, ultimately, accessible from within Python. I don't think I can get to the counter in the example above without writing a C extension.

This is discussed in slightly more depth in Talk:Python_programming_language#Closures. I like my example better, though. :)

This is largely an academic discussion; I'm not suggesting changes to the article. If Python's identity as a language supporting closures does come into question, however, maybe this will head it off. --Pgroce 14:26, 18 May 2006 (UTC)Reply

Removed "merge this with Function object" note

Closures are a critically important concept in programming languages (and computer science) and definitely deserve their own separate article. They are different from Function objects, despite the fact that the two are sometimes confused.

First, it does not concern us if a topic is imporant or not. If there is no article named closure, it would never mean that closure is an unimportant topic as long as the topic is well covered. Second, it is not clear to me the difference between the two, and since the "current" content of this article is similar to that in function object, I suggest we merge the two. -- Taku 07:45, Jun 8, 2005 (UTC)
What a silly remark is that! Why does the importance of a topic "not concern" you? Closures are an immensely important aspect of computer science, and they have nothing in common with function objects. The very minute the page on closures loses its page, I will make a new one. Wouter Lievens 09:05, 8 Jun 2005 (UTC)
Because if a closure is not an obscure topic (which it is not), we still have to cover it. I am not saying this is not important so we have to merge it with the other. It's about overlap. For example, the example given in this article resembles the idea of a function object. -- Taku 09:18, Jun 8, 2005 (UTC)
If the example is bad, then it needs to be rewritten. It doesn't mean the article has to be merged with an unrelated random other article. You might as well merge it with Lambda Calculus. Also, the example isn't a bad one, and it doesn't even closely resemble a function object, as it is expressed in ML, which isn't object-oriented. If in your view closures and function objects are the same thing, you need to get your concepts straight. Wouter Lievens 10:15, 8 Jun 2005 (UTC)
From my point of view, keeping Closure as its own topic is useful from a searching perspective. I'm realatively new to computer science concepts, and when I came across 'closure' repeatedly in literature (and without a definition), a search on Wikipedia was immediately successful. If you don't already know that a closure is related to a function object, it would be a bit harder to find. The articles should definitely reference each other; something like "A closure is very similar in most respects to a function object" in this article, and "Function objects are related to the more general concept of a closure" in the other. From what I can tell of those to articles, they are separate (though related) things, and seem to deserve separate treatment. RadiantMatrix 20:27, 23 Jun 2005 (UTC)
My concepts of function objects and closure are those put in each article.
a closure is an abstraction representing a function, plus the lexical environment (see static scoping) in which the function was created, and its application to arguments.
A function object, often called a functor, is a computer programming construct allowing an object to be invoked or called as if it were an ordinary function, usually with the same syntax.

The definition of a closure awafully resembles that of a function object in Java, for instance. Take this:

interface Function {
  public int map (int y);
}
final int step = 2;
new Function () {
  public int map (int y) { return y + step; }
}

I am not suggesting the example in the article is bad. It shows what is a closure. And I am still waiting to see what is a difference. I can't find this anywhere yet. Finally, a function object is certainly not limited to object-oriented languages. I think it's an old concept originated in functional programming. Maybe I am missing something. -- Taku 11:41, Jun 8, 2005 (UTC)

A function object is something you create in object-oriented programs to make up for the lack of proper first-class and higher-order functions (i.e. closures). OOP languages that support closures (e.g. Smalltalk) typically do not use function objects (as shown in the example), because the presence of closures removes the need for function objects. However, as closures in such languages (e.g. Smalltalk blocks) are modelled as objects, they do resemble function objects. But the typical languages where function objects are used (such as C++ and Java) do not support lexical environment closure, and thus function objects are not equivalent and not even related. The key feature of a closure is the environment link. A function object in C++ can be best compared to a function pointer in C, in that it can be invoked and passed around dynamically. Closures are not supported in C++ because the language's activation record model is entirely stack-based. Java anonymous inner classes fix this halfway by providing syntactic sugar for using final variables in the closure, but these are in fact translated to parameters to the anonymous class. So to summarize: a function object is an object that behaves semantically (and sometimes syntactically) like a function, whereas a closure is a function extended with its environment of definition. Some function objects may be in fact closures, and some closures may in fact be objects (Smalltalk blocks), which means the two concepts may overlap. But they definately don't have to. Wouter Lievens 12:43, 8 Jun 2005 (UTC)
Good now I see your distinction. But I don't think this is large enough to warrant two separate articles. Obviously not everyone sees this distinction, for one. It is true that some closures that are never function objects, and some function objects have no relation with closure. But it does not mean they cannot be discussed in one article. Certainly, the usage of a function object is similar to that of closure. And I still think, like the above post, discussing the two concepts is helpful for readers. Take negative and non-negative numbers. A negative number is never positive, but discussing two numbers in one place helps readers understand the two concepts. If you think a term function object would cause confusion, we can simply rename it. -- Taku 23:15, Jun 8, 2005 (UTC)
I think each distinct subject deserves its own page. What can possibly be gained from merging these (rather unrelated) pages together? More precisely, it would introduce serious problems in terms of categorization. For instance, function object would belong in [[Category: Object-Oriented Programming]], whereas closure (computer science) definately does not. In analogy, we might as well put President and King in the same page, as they're related too (both are heads of state). Wouter Lievens 09:56, 22 Jun 2005 (UTC)
Another reason why these can't be merged, is because of terminology tradition. Your average C++ or Java programmer has never even heard of a closure, whereas the average Scheme/Lisp/ML programmer will think function object is a contradiction in terminis. Wouter Lievens 10:01, 22 Jun 2005 (UTC)
All right. I am convinced. If not merger, we at least mention how the two differ somehow. -- Taku July 5, 2005 01:31 (UTC)

Implementation, actors, concurrency

Carl: thank you for clarifying that.

One query, though: I'm not sure if the actor model reference belongs under the heading "implementation"? ISTM that actors are related to more to abstractions than implementations. Also, the concurrency issue might deserve a section of its own, which could then also be expanded to cover the approaches taken in practice by languages like Erlang and Concurrent ML. I'll leave things unchanged myself till I've had a chance to read Clinger's thesis, though. Haeleth 15:49, August 22, 2005 (UTC)

For now I changed the section title to "Implementation and Theory"--Carl Hewitt 16:53, 22 August 2005 (UTC)Reply

Focus on state

It seems to me that the focus on "storing information" is just wrong. Am I crazy? Google says:

Definitions that do not mention storing information: [1] [2] [3] ([4]--see function closure) ([5]--see lambda) ([6]--see lexical closure) [7].

Definitions that do mention storing information: [8].

Definitions that sort of imply it: [9].

In my experience, a closure is (a) in source code, a syntactical construct where the code for a function appears, and it has open variables that are declared not within the function, but outside, in its lexical scope; (b) at run-time, the implementation of that function, consisting of some code and a pointer to the environment (where the open variables live at run-time). You can assign to open variables in some languages, true; but a lot of functional languages don't let you assign to local variables at all; this is hardly the essential, defining feature of closures. -- Jorend 21:13, 10 January 2006 (UTC)Reply

Yeah, I also found the focus on state rather weird, especially in the introductory paragraph. -Chinju 03:22, 24 January 2006 (UTC)Reply

Okay, I changed it. The current page is worse stylistically, but at least it's correct. And the new examples have some meaning. Maybe someone with more time and writing talent can help clean up my terrible wording. Jorend 00:15, 16 February 2006 (UTC)Reply

closures in prolog??

c'mon, what are you tlaking about? I will kindly remove the reference if not explained =) -- Euyyn 7-2-05