What's a Closure?

Matts on 2002-08-05T14:22:44

I talked a little bit about closures in my Exceptions talk at OSCon, taking my description from Damian's excellent book:

"In Perl, a closure is just a subroutine that refers to one or more lexical variables declared outside the subroutine itself"

Simple enough definition, right?

Well one thing I got to thinking about is file scope. Does this definition of closure extend to file scope?

e.g. instead of:

{
  my $x = 0;
  
  sub foo { print $x++ }
}
foo(); foo();


we can have:

# begin file
package Foo;

my $x = 0;

sub foo { print $x++ } __END__


.. and in a separate file:

require "file1.pl";
Foo::foo(); Foo::foo();


This appears to have the same effect - the lexical variable $x is outside of the scope when we call the function, yet that function still has access to the variable, even though that scope has "finished".

However I brought this up on #london.pm and two perl programmers I respect most highly completely disagreed with me that these are closures. And maybe they are right in that they're not implemented internally as closures, but I think they act like closures, and look like closures, so for me it's easy enough to think of them as closures.

Where was I going with all of this?

Well what I'd like to do is look into the adding some sort of "proper" class semantics to perl 5. Yes I know I should wait for Perl 6, blah blah blah, but I have reasons for doing this so don't try and persuade me not to (mostly its that I want to stop being the annoying person on p5p who has something to say about everything - the guy from MJD's presentation who ruins everyones ideas (most recently regarding YAML - I wish I'd kept my mouth shut), but who has never actually contributed to perl's core - so I want to get to know the guts and see what doing this would take).

Here's how I expect a class to look under my scheme:

class Foo;

# I'm not hot on the "invar" keyword, but it's only syntax ;-) invar $x; invar $y;

sub set_x { my ($param) = shift; $x = $param; }

sub get_x { $x; }


The idea being that $x and $y there would be "instance variables". Now really this requires a totally new variable type in perl (as far as I can tell - otherwise you have to do it with source filters, and thats not the aim here - I'm looking for OO done right, not stuck on with sticky tape). So we already have my and our variables (lexicals and package vars) but we also need instance variables.

So tying these two together - the problem with lexical vars is they become closures, and I don't want one copy of the variable being tied into the sub - I want each invocation of that sub to get the right instance variable when it is called. The problem with package variables is similar - you get one instance of them. To do this right it needs to plug deep into the perl internals, and probably gets pretty scary. Hence the desire for a new type of variable.

Anyway... signing off for now. Lots to think about.


invar

gnat on 2002-08-05T17:25:21

Or make every 'my' inside a class definition be an instance variable ...

--Nat

Re:invar

Matts on 2002-08-05T19:39:06

I reserved my() for class variables ;-)

Don't wait for Perl 6

jdavidb on 2002-08-05T17:42:49

Yes I know I should wait for Perl 6, blah blah blah, but I have reasons for doing this so don't try and persuade me not to

Why should you wait for Perl 6? Perl 5 is a perfectly viable platform for such experiments. I expect Perl 6 to arrive eventually and be worth moving to, but many people are still skeptical. Skeptical or not, the Perl 6 development effort ignited some spectacular development fireworks in the world of Perl 5, and we're all reaping the benefits. If you have ideas, don't let anyone dissuade you.

"closure" is not "anon sub"

merlyn on 2002-08-05T21:47:31

I've ranted a few times on Perlmonks when people get "closure" and "anon sub" mixed up.

A closure is any subroutine that needs to grab its environment because it's going out of scope, and may or may not be named.

An anonymous subroutine is a coderef, and may or may not be a closure.

I've got code to demonstrate all four types of subroutines (named vs anonymous, closure vs not) at Monks somewhere.

Re:"closure" is not "anon sub"

jand on 2002-08-06T20:26:57

Yes, but contrary to what #london may be claiming, both of Matts samples represent closures. :) Just check against Damians definition!

Re:"closure" is not "anon sub"

merlyn on 2002-08-07T00:19:25

Right. The examples at the top of this thread are named subroutines that are closures. Similar to this: BEGIN { my @DoW = qw(Sun Mon Tue Wed Thu Fri Sat); sub DoW { my $n = shift; die unless $n == int($n) and $n >= 0 and $n That's definitely a closure and yet it's a named subroutine.