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

Reply via email to