On 8/3/07, Patrick R. Michaud <[EMAIL PROTECTED]> wrote:
> On Fri, Aug 03, 2007 at 03:37:39PM -0700, Bob Rogers wrote:
> > A naive PIR implementation of this loop is included as the second
> > attachment. It fails miserably, because PIR can't distinguish between
> > the different scopes for "$i" and "$n".
> >
> > sub make_closures_loop {
> > # Return n closures, each with lexical references to $i and $n.
> > my $n = shift;
> >
> > my @result;
> > for (1..$n) {
> > my $i = $_;
> > push(@result, sub { print "Called sub $i out of $n.\n"; });
> > }
> > return @result;
> > }
> >
> > [...]
> >
> > ## Return n closures, each with lexical references to "I" and "N'.
> > .sub make_closures_loop
> > .param pmc n
> > .lex "$n", n
> > .lex "$i", $P42
> > [...]
> >
> > .sub internal_make_closures_loop_0 :outer('make_closures_loop')
> > find_lex $P42, "$i"
> > find_lex $P43, "$n"
> > [...]
>
> This seems wrong to me -- shouldn't $i be scoped to the internal
> loop instead of the outer one? In other words, I think the PIR
> code should read:
>
> .sub make_closures_loop
> .param pmc n
> .lex "$n", n
> ...
>
> and then
>
> .sub internal_make_closures_loop_0 :outer('make_closures_loop')
> .lex "$i", $P42
> find_lex $P43, "$n"
> ...
No, this is different. Your code puts the scope of $i inside the
anonymous sub. In other words, it's this:
for (1..$n) {
push(@result, sub { my $i = ...; print "Called sub $i out of $n.\n"; });
}
Except there's way to initialize $i in this case. (Initializing it
from $_ inside the anonymous sub just moves the problem to a different
variable.)
> Otherwise, the reason that PIR isn't able to distinguish the
> scopes is because in PIR you're actually defining them to be
> in the same scope.
I believe that's exactly Bob's point.
> However, I must confess that I still haven't grokked all of the
> ramifications of lexicals and closures in PIR yet -- and I may
> even be interpreting the p5 translation incorrectly. It just
> looks to me as though the "naive translation" isn't being faithful
> to the original p5 source, and so perhaps that's causing the
> problem you're seeing.
Again, I believe this is what Bob was saying: it's not possible to be
faithful to the original p5 source without creating a separate
subroutine for every loop body. And there are reasons why that's a bad
idea (even if that's what they are in Perl 6):
- It introduces extra overhead in terms of the compiled code
- It's extra work for the compiler – introducing an extra pass for
lexical analysis
The alternative (which Bob is suggesting) is to reintroduce
push_pad/pop_pad so you can create new lexical scopes without using
subroutines for loop bodies.
His suggestion seems reasonable to me. We won't run into this
particular problem with Tcl, but I think most languages will.
--
Matt Diephouse
http://matt.diephouse.com