develooper Front page | perl.perl5.porters | Postings from October 2003

Re: [perl #24296] scalars and hashes sometimes not available in quoted evals in END blocks

Thread Next
From:
David Dyck
Date:
October 28, 2003 10:15
Subject:
Re: [perl #24296] scalars and hashes sometimes not available in quoted evals in END blocks
Message ID:
Pine.LNX.4.51.0310280842030.15899@dd.tc.fluke.com
On Tue, 28 Oct 2003 at 10:31 -0000, Dave Mitchell <perlbug-followup@perl.or...:

> This is the correct behaviour. The showvars sub is *not* a closure (it
> doesn't have a compile-time mention of the outer lexical), while the END
> sub *is a closure. Thus at compile time the END sub captures the first
> (and only) instance of $my_scalar. By the time END is called, the pad for
> the main code block has already been freed, so the var isn't available.
> But END has its own private reference to it, so the END sub can still
> access it.
>
> You can see a similar affect in this piece of code (not involving END):
>
>     {
> 	my $x = 55;
> 	sub f1 { print "f1: x=$x\n" }
> 	sub f2 { print "f2: x=", eval '$x', "\n" }
>     }
>
>     f1;
>     f2;
>
>     __END__
>
>     f1: x=55
>     Variable "$x" is not available at (eval 1) line 2.
>     Use of uninitialized value in print at /tmp/p line 7.
>     f2: x=
>
> Dave.

Thanks for responding!  Could we please start with
 This is the implemented behaviour. :-)
and work towards
 This is not the documented behaviour.
or at least
 This is not the do-what-I-mean behaviour.

I'm not sure I understand, or at least I have more to learn
in this area.  The my variable that I declared was at file
scope, and if we modify your case to move $x to file scope,
then both of the functions can see $x.

I think you are describing what perl is doing, and
we both observe that something is happening (something
that I don't expect), but from my reading of the
documentation I didn't pick up on the limitations of END subs
that you are stating.

I do see the statement in perlsub.pod that states:
 The "my" operator declares the listed variables to be
 lexically confined to the enclosing block,
 ...  or "do/require/use"'d file.

and

 An "eval()", however, can see lexical variables of the
 scope it is being evaluated in, so long as the names
 aren't hidden by declarations within the "eval()" itself.
 See perlref.



Examples like the following that do what I mean
lead me to think that the my initial bug report
shows that perl isn't dwim'ing.


    my $x = 55;
    {
	sub f1 { print "f1: x=$x\n" }
	sub f2 { print "f2: x=", eval '$x', "\n" }
    }

    f1;
    f2;

    __END__

    f1: x=55
    f2: x=55

And even here

    my $x = 55;
    END {
	sub f1 { print "f1: x=$x\n" }
	sub f2 { print "f2: x=", eval '$x', "\n" }
	f1;
	f2;
    }

    __END__

    f1: x=55
    f2: x=55



The reason I even started looking into this is
that I have some real code (vs. the example code
that I posted) that whas having elements of
a hash table disappearing during the END processing.


Ok, here's another example that may be closer so showing
the problem.

The very same eval in one case can see $x, but
when other code is removed then perl issues warnings
The evals in the first and third END subs
have $x available, but not the second.

Please help me find the perl documentation
that describes this as the correct behaviour.

    use warnings;
    use strict;
    $| = 1;

    # 2 lines from perlsub
    my $x = 10;
    sub bumpx { $x++ }

    eval 'print "x=$x\n"';
    bumpx;
    eval 'print "x=$x\n"';

    END {
	print "in first END\n";
	eval 'print "in eval x=$x\n"';
	bumpx;
	eval 'print "in eval x=$x\n"';
	$x;	# commenting out this line causes the
	    # above eval's to loose their access to $x
    }

    END {
	print "in second END\n";
	print "END\n";
	eval 'print "in eval x=$x\n"';
	bumpx;
	eval 'print "in eval x=$x\n"';
    ### $x;	# commenting out this line causes the
	    # above eval's to loose their access to $x
    }

    END {
	print "in third END\n";
	eval 'print "in eval x=$x\n"';
	bumpx;
	eval 'print "in eval x=$x\n"';
	$x;	# commenting out this line causes the
	    # above eval's to loose their access to $x
    }

    __END__

    x=10
    x=11
    in third END
    in eval x=11
    in eval x=12
    in second END
    END
    Variable "$x" is not available at (eval 5) line 1.
    Use of uninitialized value in concatenation (.) or string at (eval 5) line 1.
    in eval x=
    Variable "$x" is not available at (eval 6) line 1.
    Use of uninitialized value in concatenation (.) or string at (eval 6) line 1.
    in eval x=
    in first END
    in eval x=13
    in eval x=14

Thread Next


nntp.perl.org: Perl Programming lists via nntp and http.
Comments to Ask Bjørn Hansen at ask@perl.org | Group listing | About