develooper Front page | perl.perl5.porters | Postings from July 2012

[perl #113930] Lexical subs

Thread Previous | Thread Next
From:
Father Chrysostomos
Date:
July 1, 2012 14:23
Subject:
[perl #113930] Lexical subs
Message ID:
rt-3.6.HEAD-28836-1341177806-405.113930-75-0@perl.org
# New Ticket Created by  Father Chrysostomos 
# Please include the string:  [perl #113930]
# in the subject line of all future correspondence about this issue. 
# <URL: https://rt.perl.org:443/rt3/Ticket/Display.html?id=113930 >


There doesn’t appear to be a ticket for this already, so I’m making one.  There is also another reason: I think I know how to make it work.

The last time this came up, the two main issues were:

1)

If ‘my sub’ follows the same scoping rules as existing my and sub declarations, then the lexical sub will not be visible inside itself, unless declared beforehand.  But if ‘my’ creates a new pad entry, then this won’t work:

my sub foo;
my sub foo { ... }

because the second one creates a new pad entry and does not modify the existing one.

2)

Should declarations be compile-time or run-time?  If they are compile-time declarations, then how does one redefine a sub (c.f. problem 1); and how does a lexical sub close over variables?  If it is a run-time thing, then it is radically different from ‘sub foo {...}’, so shouldn’t it look different?

These questions can be summarized as: When does a lexical closure close over outer variables?  What else has to happen to make it work?

----------------------------------------------------------------------

I think the solution to #1 is to make ‘sub foo { ... }’ respect a lexical declaration that precedes it.  Just as $x = 3 does not assign to the package variable $x after a my $x declaration, so ‘sub foo { ... }’ should not create a package sub after ‘my sub foo;’.

That in itself pretty much resolves #2, but we have (at least) two variants:

• Lexical subs close over variables when the name comes into scope (which could happen multiple times with loops).
• Lexical subs close over variables when referenced or called.
• Lexical subs close over variables when *first* referenced or called.

For the most part, there is no observable difference here, until it comes to referential identity and for loops.

I don’t think we have to worry about referential identity, since optimisations would make all three variants nearly identical in that regard.

For for loops we have to decide what this will do:

for my $x (1..10) {
    my sub foo { push @results, $x }
    foo();
}

The @results will be 1..10, 1..10 and (1)x10, respectively for the three variants.

And what about this?

my sub foo;
for my $x (1..10) {
    sub foo { push @results, $x }
    foo();
}

Results: (undef)x10, 1..10, (1)x10

And this would produce the same:

my $x;
my sub foo { push @results, $x }
for $x (1..10) {
    foo();
}

In all these cases, the second variant seems more intuitive, at least to me.  In fact, that’s similar to how format closures work.  This prints the numbers from 1 to 10:

my $x;
format =
@<<<<<<
$x
.
for $x (1..10) {
   write;
}

If we introduce lexical aliases via \my $x = $y, we will need to figure this out for the sake of that, too.

-----------------------------------------------------------

Next issue:  What should state sub do?  Should it behave the same way as my sub?  Should it close over the variables the first time through the function?  Should it be an error (currently it is not) until we decide?

I think it should be just a named package sub (‘Variable will not stay shared’ and all), but visible only in a lexical scope.

-----------------------------------------------------------

I think it is pretty obvious that our sub should create a lexical alias to a package sub, so that this will work:

sub foo { warn "main" }
package bar;
foo(); # calls main::foo

-----------------------------------------------------------

‘my format’ and ‘my package’ would be going a bit too far. :-)


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