Beefy Boxes and Bandwidth Generously Provided by pair Networks
Keep It Simple, Stupid
 
PerlMonks  

Closure warning with Perl 5.14?

by BerntB (Deacon)
on May 19, 2011 at 08:27 UTC ( #905630=perlquestion: print w/ replies, xml ) Need Help??
BerntB has asked for the wisdom of the Perl Monks concerning the following question:

I ran some tests on Perl 5.14, which works well on 5.12.2.

I got this warning on a closure: Variable "$color" is not available at /.../FindingsParser.pm line 1763.

The code isn't pretty, but it doesn't do anything too abnormal.

sub make_csv_format { my $me = shift; my $color = shift if @_; my $quote_item = sub { # ... # Remove ugly kludge with prefixed color information: $item =~ s/^#[\dA-F]{6}//i unless $color; # ... }; # <------ This is line with warning. my $quote_row = sub { my $items = shift; return join(",", map { $quote_item->($_) } @$items) . "\n"; }; # ... }

This might theoretically be Perl 5.14 (or the perlbrew install?) -- with a problem when one closure calls another, or something. But to be realistic, it is me. :-) I don't get warnings from other closures.

Comment on Closure warning with Perl 5.14?
Download Code
Re: Closure warning with Perl 5.14?
by BrowserUk (Pope) on May 19, 2011 at 08:36 UTC
    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.

      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?

        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.
        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.
        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.

Re: Closure warning with Perl 5.14?
by wind (Priest) on May 19, 2011 at 08:44 UTC
    Remove the if after the declaration of $color. It serves no purpose and is leading to the error:
    my $color = shift;
    If you were ever to need initialize a variable conditionally, be sure to use the ternary operator
    my $variable = $condition ? 'value' : undef;

      Thanks. Yeah, that is the way to remove the warning.

      The parameter is documented as optional, so I thought the code looked most obvious like that. I'll update my Best Practices.

      By coincidence I have been having a similar problem in 5.8.2. When assigning a variable to a match backreference, at outer scope there was no warning when the match failed. When assigning it to a variable at level 1 loop scope from within a level 2 loop, it gave the warning that something was uninitialised in the match expression (an untrue statement). Furthermore, even using the ternary operator to force the variable to '' on match failure, the match warning was delayed until the variable was subsequently tested with a simple "if ($var)" at which point it made even less sense. I get the impression that Perl can sometimes catch its feet slightly when trying to process potential uninitialisation for variables being updated or initialised in a different lexical and sub-global scope from which they were declared.

      One world, one people

Re: Closure warning with Perl 5.14?
by ikegami (Pope) on May 19, 2011 at 09:50 UTC

    You can get that warning from the following even before 5.14:

    use strict; use warnings; sub foo { my ($x) = @_; return sub { eval 'print "$x\n";' }; } sub bar { my ($x) = @_; return sub { $x if 0; eval 'print "$x\n";' }; } foo("foo")->(); bar("bar")->();

    (Note: The if 0 just avoids a void context warning. Removing it doesn't change the outcome.)

    That you also get it in 5.14 under some circumstances involving illegal code (my ... if ...;) is not a problem.

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://905630]
Approved by salva
Front-paged by toolic
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others pondering the Monastery: (8)
As of 2014-09-19 02:06 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    How do you remember the number of days in each month?











    Results (129 votes), past polls