Search code examples
perl

What is wrong in "my $foo = $x if $y" syntax?


In my last question here, @amon gave an great answer. However, he told too:

First of all, please don't do my $foo = $x if $y. You get unexpected and undefined behavior, so it is best to avoid that syntax.

Because the above construction I was see in really many sources in the CPAN, I'm wondering how, when, where can be it wrong. (Some example code would be nice). Wondering too, why perl allows it, if it is bad.


Solution

  • His wording was actually a bit laxer. That wording is actually mine. Let's start with the documentation: (Emphasis in original)

    NOTE: The behaviour of a my, state, or our modified with a statement modifier conditional or loop construct (for example, 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.

    To be more precise, the problem is using a lexical variable when its my may not have been executed.

    Consider:

    # Usage:
    #   f($x)  # Store a value
    #   f()    # Fetch and clear the stored value
    
    sub f {
       my $x if !@_;
       if (@_) {
          $x = $_[0];
       } else {
          return $x;
       }
    }
    
    f('abc');
    say "<", f(), ">"   # abc
    

    This is obviously not the documented behaviour of my.

    Because the above construction I was see in really many sources in the CPAN

    That code is buggy. If you want a value to persist between calls to a sub, you can use a state variable since Perl 5.10, or a variable outside of the sub.