develooper Front page | perl.perl6.language | Postings from August 2001

Re: explicitly declare closures???

Thread Previous | Thread Next
From:
Dave Mitchell
Date:
August 21, 2001 10:06
Subject:
Re: explicitly declare closures???
Message ID:
200108211706.SAA10234@gizmo.fdgroup.co.uk
Piers Cawley <pdcawley@iterative-software.com> wrote:
> > {
> >     my $x = "bar";
> >     sub foo {
> > 	# $x  # <- uncommenting this line changes the outcome
> > 	return sub {$x};
> >     }
> > }
> > print foo()->();
> 
> Well, I would expect it to output 'foo' on both occasions, and I'm
> more than a little surprised to discover that it doesn't. Looks like a
> bug to me.

Using the notation $outer:x, $foo:x and $anon:x to refer to whatever
$x might be in the 3 scopes:

With the $x:

foo() is a closure created at compile time. By the time the main {} block
has been executed (but before foo() is called), the $outer:x is undef,
and $foo:x is 'bar' (standard closure stuff). When foo() is executed,
the anon sub is cloned, and at that time, $anon:x is set from from foo's pad,
so it gets 'bar'.

Without the $x:

foo is no longer a closure - ie it doesnt have a private copy of $x in
its pad. At cloning time, sub {$x} picks up its value of $x from $outer:x,
since there isn't a $x in foo's pad - thus it picks up 'undef' from $outer:x
that went out of scope a while ago.

If there was an explicit declaration that your were closing (is that
the right verb?), it might be clearer to the user what what going on.

{
  my $x = "bar";
  sub foo {
    # my outer $x;  # <- uncommenting this line changes the outcome
    return sub {my outer $x};
  }
}
print foo()->();

(I've changed 'closure' to 'outer' since John Porter's just pointed
out to me privately that 'closure' is grammatical nonsense)

Or to put it all another way....

Any bare use of a lexical in an inner sub, such as "$x" is roughly
equivalent to

my $x = copy_of_the_value_at_compile_or_clone_time_of_the_outer($x);

so a bare '$x' has the combined implicit actions of creating a new $x
for the current scope (or even till the end of the current sub), and
initialising to a partiular value at a particular time. That's quite
a lot of semantic baggage attached to an innocent bare var!

So instead, I'd like

"$x" to be an error, and
"my outer $x" to be shorthand for
my $x = copy_of_the_value_at_compile_or_clone_time_of_the_outer($x);

But I can see I'm not on to a winner here....



Thread Previous | Thread Next


nntp.perl.org: Perl Programming lists via nntp and http.
Comments to Ask Bjørn Hansen at ask@perl.org | Group listing | About