in reply to Re: Re: Re: Re: Re: Re^3: Perl to Ruby translator?
in thread Perl to Ruby translator?

Well, now I understand the mechanics behind it becoming a closure, but why on earth would perl make it a closure? That doesn't make any sense to me. Why wouldn't the sub just use whatever $q it can find in the closest scope to it?
  • Comment on Re: Re: Re: Re: Re: Re: Re^3: Perl to Ruby translator?

Replies are listed 'Best First'.
Lexicals, Pads, and Closures
by chromatic (Archbishop) on Oct 11, 2003 at 22:21 UTC

    That's exactly what makes it a closure.

    Lexical variables live in their own symbol tables (that's not what they're called in Perl 5, but it's the concept: just a mapping of a name to the data structure that represents the appropriate variable container). They nest — that's why you can write code like this:

    my $foo = 'outside'; { my $foo = 'inside'; print "Inside: '$foo'\n"; } print "Ouside: '$foo'\n";

    If you dump the optree with something like B::Concise, you'll see enter, leave, and pad operations. The enter and leave ops govern which symbol table (scratch pad or lexical pad, in Perl 5 terms) is active. Think of it like a stack and you'll get it. The pad operations look up a symbol in the scratch pad.

    Subroutines (anonymous and named) are represented by data structures called CVs (basically, Code Values). Every CV is attached to a lexical symbol table. That's just a place to store the lexical variables declared and used within that subroutine.

    To handle the nesting issue, there has to be a way to look outward from inner scopes. If there's no $foo in the tightest, most innermost scope, look outward, one scope at a time, to find the nearest appropriate $foo. (This is complicated a little bit by global variables, which are handled with a different symbol table implementation in Perl 5. There also appears to be variable analysis because of the pad ops, not glob ops. Insert handwaving here; I really don't want to read that code right now.)

    The code example you're asking about is a closure so that nested variable scopes will work. Or, put the way it actually happened, because nested variable scopes had to work, closures were possible.

Re: Re: Re: Re: Re: Re: Re: Re^3: Perl to Ruby translator?
by runrig (Abbot) on Oct 13, 2003 at 17:48 UTC
    It is not a problem when run as is, because it does not really create a closure when the lexical is declared at the top level outside of any subroutine (I may be wrong, but it's at least a closure that doesn't create any problems...yet). So this works ok:
    use strict; use warnings; my $foo = 'foo'; bar(); $foo = 'bar'; bar(); sub bar { print "$foo\n"; }
    The problem comes when the script is run under Apache::Registry, because it turns the script into something like this:
    sub foo1234 { use strict; use warnings; my $foo = 'foo'; bar(); $foo = 'bar'; bar(); sub bar { print "$foo\n"; } } # Execute once foo1234(); # Execute twice foo1234(); OUTPUT: foo bar bar bar
    This gives you '$foo will not stay shared' warnings, and the result is that '$foo' does not change after the first execution of the subroutine that Apache::Registry wraps your script in. And mod_perl executes this subroutine over and over again (that's how Apache::Registry keeps your script persistent within mod_perl).