JadeNB has asked for the wisdom of the Perl Monks concerning the following question:

I have an issue where a variable seems unexpectedly to be going out of scope.
{ my $v = 1; sub mk_view_v { $v; sub { $v }; } } print "(", mk_view_v()->(), ")\n";
prints (1), as one would expect. However, that void-context $v looks mighty silly, so we might try commenting it out:
{ my $v = 1; sub mk_view_v { # $v; sub { $v }; } } print "(", mk_view_v()->(), ")\n";
Now we print just () (UPDATE: with a complaint about undefined variables, if we are well behaved and use warnings).

I can't come up with anything but fanciful guesses for why this happens, but note that

{ my $v = 1; sub mk_mk_view_v { $v; sub { sub { $v } }; } } print "(", mk_mk_view_v()->()->(), ")\n";
still sees the declared value of $v, and still stops seeing it if one comments out the $v line.

By the way, "This is perl, v5.8.9 built for darwin-2level" (installed via MacPorts). The behaviour seems to have gone away in 5.10.0.

UPDATE: Thanks to QM for pointing out that $a was a bad choice of variable. I changed it to $v, and made the subroutine names slightly more informative while I was at it. :-)

Replies are listed 'Best First'.
Re: Vexing views of variables
by QM (Parson) on Aug 07, 2009 at 18:43 UTC
    Perhaps irrelevant, but $a and $b are special for sort, and should never be used elsewhere, unless you are expecting sort to call the sub.

    -QM
    --
    Quantum Mechanics: The dreams stuff is made of

      I think that lexical $a and $b are still OK (and have no significance to sort), but you're right that they're sub-optimal choices of names. I've changed it—thanks!
Re: Vexing views of variables
by ig (Vicar) on Aug 07, 2009 at 19:24 UTC

    FWIW: similar behavior on CentOS 5.3: v5.8.8 has the bug and v5.10.0 does not.

    perl590delta says:

    There have been many fixes in the area of anonymous subs, lexicals and closures. Although this means that Perl is now more "correct", it is possible that some existing code will break that happens to rely on the faulty behaviour. In practice this is unlikely unless your code contains a very complex nesting of anonymous subs, evals and lexicals.
      Thanks, that seems to cover it! (Sorry, I was too lazy to grep through deltas myself (not least because I didn't know for what to search (and I wonder who (not me!) would ever have thought that I might run into trouble with excessive nesting?)).)
Re: Vexing views of variables
by Marshall (Canon) on Aug 07, 2009 at 19:43 UTC
    #!/usr/bin/perl -w use strict; { my $v = 1; sub mk_view_v { $v; ## <<< this is an error sub { $v }; #<<<this is a no op ?? #anon sub declaration that if called #would return $v ## but if $v is 1; then mk_view_v() returns 1; ## well maybe not, maybe this is supposed to ## return a ref to the anon sub{}? ## this still looks strange to me # weird } } print "(", mk_view_v()->(), ")\n"; # very strange print statement
    prints (1), as one would expect.

    I would like someone to walk me thru how
    mk_view_v()->() generates the expected "1"!!!

    I find the above code bizarre.
    What this ->() is supposed to call the anon sub within mk_view_v()?

      The void-context $v is not an error, but it does generate a warning, which I didn't notice because I was naughty and didn't use warnings for my test script. Changing it to { no warnings 'void'; $v; } silences the warning (by brute force) and has the same effect.

      sub { $v } would normally be a no-op, but, here, it's the last line statement of a function definition, so it carries an implicit return. Thus, mk_view_v() returns that anonymous sub, and we call it as we would any other coderef.

      UPDATE: I should have said that the sub { $v } line carries 2 implicit returns—more explicitly, it's return sub { return $v }.