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

I'm having an interesting dilemma with Error.pm and END blocks that I was hoping I could get some insight into. I appreciate any help anyone can give.

The problem is as follows:

#!/usr/bin/perl -w use strict; use Error qw( :try ); my $var = "Hello"; END { print $var, "\n"; try { print $var, "\n"; } catch Error with { print "Whoa, got an error!\n"; }; }


Gives me:
Hello
Hello

while this:
#!/usr/bin/perl -w use strict; use Error qw( :try ); my $var = "Hello"; END { try { print $var, "\n"; } catch Error with { print "Whoa, got an error!\n"; }; }


gives me
Use of uninitialized value in print at testend2.pl line 11.

I could see the second one not working, but why does printing (or just using or even just saying $var;) make it work inside the try block??

Is this a problem with Error.pm or a standard issue occurrence?

--------------
It's sad that a family can be torn apart by such a such a simple thing as a pack of wild dogs

Replies are listed 'Best First'.
Re: Variables out of scope using END and Error.pm
by dave_the_m (Monsignor) on Feb 17, 2005 at 19:53 UTC
    It's a problem with closures in current versions of perl. Named subs (such as END) don't close on behalf of inner anonymous subs (such as the try block effectively is), so the variable goes out of scope before END is called. The presence of the variable directly in the END sub causes the variable to be captured and thus live long enough for END to be called. It's already fixed (by me :-) in the development branch of perl:
    $ cat /tmp/p #!/usr/bin/perl -w my $x = 1; END { sub { print "x=$x\n" }->(); } $ perl586 /tmp/p Use of uninitialized value in concatenation (.) or string at /tmp/p li +ne 5. x= $ perl590 /tmp/p x=1 $

    Dave.

      I'm not sure if that explenation is 100% correct...

      If for example you change 'END' to sub abc (or anything, which is a named sub aswell) else and call it, then it does print 1.

        I'm not sure if that explenation is 100% correct...
        On the other hand, I am sure :-)

        The only difference between END and a normal sub in this case is that the END is called after the variable has normally gone out of scope. The following demonstrates the buggy behaviour for ordinary subs (on perl < 5.9.0) by artifically reducing the scope of the variable

        { my $x = 1; sub foo { # commenting this out causes the print to see an undef value $x; sub { print "x=$x\n" }->(); } } foo();

        Dave.

Re: Variables out of scope using END and Error.pm
by Animator (Hermit) on Feb 17, 2005 at 19:58 UTC

    From what I can tell it seems to be a problem related to the CHECK/BEGIN/INIT/END block.

    This for example does not work either: perl --wle '$,=" & ";my @c=1..2;sub xyz (&) { my $z=shift;$z->(); &$z(); &$z; } END { xyz { print "X: ", @c; }; }', but adding @c; to it then you get the warning 'useless use of private array in void context'... The keyword in this sentence would be private.

    I do not know what exactly this means...

    Update: I should have know that I would get downvoted... A question that actually seemed intresting and for which I actually tested some code... That just can't be allowed?