in reply to Closure warning with Perl 5.14?

I don't get warnings from other closures.

It is because the declaration of $color is conditional.

my $color = shift if @_;

If you only pass 1 parameter to the outer sub, $color will never be declared, so won't (can't) be available to the inner sub.

If you just dropped the conditional, the code would work properly. If you shift a value from an empty array into a scalar it will be set to undef which will work fine in the inner sub conditional.


Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
"Science is about questioning the status quo. Questioning authority".
In the absence of evidence, opinion is indistinguishable from prejudice.

Replies are listed 'Best First'.
Re^2: Closure warning with Perl 5.14?
by BerntB (Deacon) on May 19, 2011 at 08:45 UTC

    Thanks for the answer!

    But shouldn't there be a warning in 5.12? Shouldn't the warning be consistent in 5.14? I don't get a warning from this in 5.14.0:

    use warnings; use strict; my $x = <>; my $y = "X" if $x =~ /X/; $y = "Z" if !defined $y; print "$y\n";
      But shouldn't there be a warning in 5.12?

      There should have been a warning for that in perl 5.0.

      Shouldn't the warning be consistent in 5.14?

      Variables declared in a conditional always was "undefined" behavior. To quote perlsyn:

      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.

      (emphasis mine). The perl-5.14.0 behavior (new warning) is consistent with the documentation, and a good thing.

        Ahh... there was the documentation, I should have looked a bit more. :-( Thanks.
      But shouldn't there be a warning in 5.12?

      Perhaps this is a new warning for old problem added in 5.14 to help us.

      I don't get a warning from this in 5.14.0: ...

      No. There is no closure involved there.

      Try:

      use warnings; use strict; my $x = <>; my $y = "X" if $x =~ /X/; sub x{ print $y ? 'Okay' : 'bad'; } print "$y\n";

      Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
      "Science is about questioning the status quo. Questioning authority".
      In the absence of evidence, opinion is indistinguishable from prejudice.

        Still no warning, $y is declared as it always was.

        (But you get a warning for an uninitialized value in a concatenation, potentially, etc.)

      But shouldn't there be a warning in 5.12?
      It warns, but only if Perl can, at compile time, determine that the condition is false.

        Yeah, I don't understand having a warning for "my ... if 0;" but not for other "my ... if ...", especially since the second construct is more likely to be a real bug.

        The warning for "my ... if 0;" should convey something along the lines of "stop doing that hack to get 'state' variables as we won't guarantee that it will continue to work". The warning for other "my ... if ...;" should convey "you've got a bug there; move the 'my' out from under the 'if'".

        It is silly to warn for something that actually works fine but in theory might stop working some day while silently accepting something that just indicates a mistake (I've never seen code that intentionally and correctly used the behavior of "my ... if maybe();"), and a subtle mistake that is easy to not notice in testing. The second case is much more deserving of a warning.

        - tye        

        This complains about uninitialized value (of course), but gives no warning in 5.14.0:

        use warnings; use strict; use constant duh => 0; my $y = "X" if duh; sub x{ print $y ? 'Okay' : 'bad'; } x(); print "$y\n";

        And no warning even for this:

        use warnings; use strict; my $y = "X" if 0; sub x{ print $y ? 'Okay' : 'bad'; } x(); print "$y\n";