in reply to quantum behavior in perl?

Here is a small program that displays the exact problem I encountered. It has to have at least two files to display this behavior.

The first is a file I call temp.pl which contains

use temp1; temp1::init(); print "Calling work1: "; temp1::work1('$var'); print "\nCalling work2: "; temp1::work2('$var');

The second file is a package temp1.pm which contains

package temp1; my $var; sub init { $var = 1 } sub work1 { print eval $_[0]; } sub work2 { print eval $_[0]; $var = $var; } 1;

The resulting output is:

Calling work1: Calling work2: 1

What is really impressive is that the print in &work2 works even though the modification is after the print statement! This is beyond quantum.

If I change the my $var to our $var everything works.

tye explains that perl, not seeing any mention of the lexical $var in &work1, assumes that &work1 does not use it, so the context of the eval does not define that variable. Doing the 'right thing' would be too expensive.

This is clearly an unsafe optimization, so it appears that some warning is needed. The documentation about the eval function mentions nothing of the sort. Clearly having compiler warnings for every instance of eval seems ridiculous, but I feel that something about this needs to be in the main documentation about the eval function.

Replies are listed 'Best First'.
Re^2: quantum behavior in perl?
by mr_mischief (Monsignor) on Aug 20, 2007 at 03:08 UTC
    The documentation about the eval function mentions nothing of the sort. Clearly having compiler warnings for every instance of eval seems ridiculous, but I feel that something about this needs to be in the main documentation about the eval function.
    Patches welcome.

    Your example is actually working with two completely different scopes. Consider this:

    use temp1; use warnings; use strict; temp1::init(); use temp1; use warnings; use strict; temp1::init(); print "Calling work1: " . temp1::work1( '$var = 3' ) . "\n"; print "Calling work2: " . temp1::work2( '$var++' ) . "\n"; print "Calling work3: " . temp1::work3( '$var++' ) . "\n"; print "Work3 again: " . temp1::work3( '++$var' ) . "\n"; print "Calling work4: " . temp1::work4( '$var++' ) . "\n";
    package temp1; use strict; use warnings; my $var; sub init { $var = 101 } sub work1 { return eval shift; } sub work2 { my $foo = shift; return eval $foo; $var } sub work3 { return eval $_[0]; } sub work4 { eval $var; } 1;
    The output is:
    Calling work1: 3 Calling work2: 101 Calling work3: 3 Work3 again: 5 Calling work4: 102