http://www.perlmonks.org?node_id=318233


in reply to Re: = rather than =~ ?
in thread = rather than =~ ?

$foo = $1 if /(foo)/;
may be okay, but
my $foo = 1 if /(foo)/;
is not.

Replies are listed 'Best First'.
Re^3: = rather than =~ ? (too brief?)
by Aristotle (Chancellor) on Jan 02, 2004 at 04:22 UTC
    If you feel the need point that one out, you should probably also explain why that is.. :)

    Makeshifts last the longest.

      $foo = $1 if /(foo)/; may very well be the expected behaviour in certain situations where we want to modify $foo if the match is successfull or leave it otherwise. Using it when declaring a variable is not desirable however. If there is no match, then $foo will not be declared and any attempt to read the scalar later will result in a "variable not declared" error. Of course, this is why we use strict;. Without it, we won't get an error :) defined.

      Basically, $foo = $1 if /(foo)/; should really only be used where we might otherwise do a $foo = /(foo)/ ? $1 : $foo; (which is just programatically ugly).

      Update: Whoa, was I off base. Read the replies to this node to see the reason :)

        One should never, ever write "my $foo = 1 if /(foo)/;". From perlsub:

        NOTE: The behaviour of a "my" statement modified with a statement modifier conditional or loop construct (e.g. "my $x if ...") is undefined. The value of the "my" variable may be "undef", any previously assigned value, or possibly anything else. Don't rely on it. Future versions of perl might do something different from the version of perl you try it out on. Here be dragons.
        No, that is wrong. Satisfying strict depends only on the compile-time effect of my, for which its mere presence suffices. However, a conditional prevents its run-time effect of allocating a new scalar for that lexically scoped name, so that the name remains associated with the previously used variable. Observe:
        use strict; use warnings; sub remember { my $memory if 0; print "Previous value of \$memory: $memory\n"; $memory = shift; } remember "foo"; remember 42; remember "bar"; remember; __END__ Use of uninitialized value in concatenation (.) or string at - line 6. Previous value of $memory: Previous value of $memory: foo Previous value of $memory: 42 Previous value of $memory: bar
        This if 0 hack has been known for a long time and might even be useful if it weren't such a dirty trick. An actual condition in that place nearly certainly means that someone is going to be very surprised.

        Makeshifts last the longest.

        I think I understand what you/they mean, but the empirical evidence says different.

        p:\test>perl -Mstrict -lwe"my $foo=1 if 'X' =~ /Y/; print 'Result is: +', $foo; " Use of uninitialized value in print at -e line 1. Result is: p:\test>perl -Mstrict -lwe"my $fob=1 if 'X' =~ /Y/; print 'Result is: +', $foo; " Global symbol "$foo" requires explicit package name at -e line 1. Execution of -e aborted due to compilation errors.

        In both examples, $foo in the print statement has never been assigned a value.

        In the first example, the compiler has seen the declaration and so only it's definedness is a problem and we get the "Use of uninitialized value" warning.

        In the second case, it is not only undefined, it doesn't exists and so we get the "Global symbol "$foo" requires explicit package name" error.

        It clearly indicates that although the if condition is false and the assignment is never performed, the my declaration has been see and acted upon.

        This is true with 5.6.1 and 5.8.1. Maybe the documentation is out of date?


        Examine what is said, not who speaks.
        "Efficiency is intelligent laziness." -David Dunham
        "Think for yourself!" - Abigail
        Hooray!