Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl Monk, Perl Meditation
 
PerlMonks  

Name "main::a" used only once: possible typo

by szabgab (Priest)
on Mar 05, 2013 at 18:24 UTC ( [id://1021888]=perlquestion: print w/replies, xml ) Need Help??

szabgab has asked for the wisdom of the Perl Monks concerning the following question:

use strict; use warnings; use List::Util qw/reduce/; print reduce { $a * $b } 1..6;
Genetates the following warnings:
Name "main::a" used only once: possible typo at x.pl line 6. Name "main::b" used only once: possible typo at x.pl line 6.
OTOH
use strict; use warnings; print sort {$a <=> $b } 1..6;
does not generate the warnings. As expected. (running perl 5.14.2 and List::Util 1.27)

Why did the first example generate the warnings?
What is the recommended way to silence them?
Why is this not mentioned in List::Util?

Replies are listed 'Best First'.
Re: Name "main::a" used only once: possible typo
by davido (Cardinal) on Mar 05, 2013 at 20:10 UTC

    This is a common problem with no known great solution (if there is a great solution I hope someone will show it so that we can submit patches). It also annoys anyone using List::MoreUtils pairwise, for about the same reason. Several ideas were tossed around in the List::MoreUtils RT as to how to fix the problem, but none were ideal, and none fixed it in 100% of use cases (including my attempt).

    The easiest solution is still annoying, and looks like this:

    reduce { no warnings 'once'; $a * $b } 1 .. 6;

    Update: I see that the List::Util RT suggests something like this:

    reduce { our ( $a, $b ); $a * $b } 1 .. 6;

    Dave

        I'd probably put the our ($a,$b) outside of that block, but this is what I had in mind. I was just interested in more options. - Thanks
        out ($a, $b); reduce { $a * $b } 1 .. 6;
Re: Name "main::a" used only once: possible typo
by toolic (Bishop) on Mar 05, 2013 at 18:58 UTC
Re: Name "main::a" used only once: possible typo (limitations of "sort" like functions)
by LanX (Saint) on Mar 05, 2013 at 21:57 UTC
    Hi Gabor

    > Why did the first example generate the warnings?

    Wrong question. Since sort is a built-in, it was able to silence the warnings!

    > What is the recommended way to silence them?

    Use them twice?

    > Why is this not mentioned in List::Util?

    Maybe because the author is frustrated about not beeing able to simulate a built-in?

    Seriously ...

    ... it's not that easy to design functional constructs with special variables in code-blocks like sort does.

    I tried it in hgrep and then I was confronted with many scoping problems, what if the block is defined within another package or if $a and $b are declared as lexicals?

    Look into the code of Hash::MostUtils to have an idea about the complications to solve all of this.

    I bet that List::Util couldn't solve all of this.

    UPDATE

    To prove my last guess:

    This prints 55, but after uncommenting the second line its only 0 ...oops!

    use List::Util qw/reduce/; # my ($a,$b)=(0,0); print reduce { $b+=$a } 1..10;

    UPDATE

    and here the same problem for List::MoreUtils

    use warnings; use strict; # my ($a,$b)=(0,0); use List::MoreUtils qw/pairwise/; my @a = (1 .. 5); my @b = (11 .. 15); my @x = pairwise { $a + $b } @a, @b; # returns 12, 14, 16, 18, 20 use Data::Dump; dd \@x;

    UPDATE

    At least sort simply dies

    my ($a,$b)=(0,0); print sort { $b cmp $a } 1..10;

    Can't use "my $b" in sort comparison at ... line 2.

    Update
    ...but
    use warnings; use strict; our ($a,$b); package Tst; print sort { $b cmp $a } 1..10;
    Use of uninitialized value $b in string comparison (cmp) at /home/lanx +/B/PL/PM/ScopeListUtils.pl line 9. Use of uninitialized value $a in string comparison (cmp) at /home/lanx +/B/PL/PM/ScopeListUtils.pl line 9. Use of uninitialized value $b in string comparison (cmp) at /home/lanx +/B/PL/PM/ScopeListUtils.pl line 9. Use of uninitialized value $a in string comparison (cmp) at /home/lanx +/B/PL/PM/ScopeListUtils.pl line 9. ...

    Cheers Rolf

      LanX, what I don't understand is why this warning, and the way to deal with it by the user of the module is not mentioned in the documentation as a limitation of perl/the module.

      If the situation I described is real, then I assume many people bump into it and many people think they are doing something wrong.

      So unless the code I wrote has the flaw, it would IMHO better to warn the user about the warning.

        > LanX, what I don't understand is why this warning, and the way to deal with it by the user of the module is not mentioned in the documentation as a limitation of perl/the module.

        I can only suppose that the problems are so overwhelming, that the authors don't know how to describe them.

        Cheers Rolf

Re: Name "main::a" used only once: possible typo
by Khen1950fx (Canon) on Mar 06, 2013 at 03:33 UTC
    Maybe this is satisfactory?
    #!/usr/bin/perl -l use strict; use warnings FATAL => 'syntax'; use List::Util qw/reduce/; print reduce( sub { $a * $b; }, 1..6);
Re: Name "main::a" used only once: possible typo
by kcott (Archbishop) on Mar 08, 2013 at 08:07 UTC

    G'day szabgab,

    I see you've got explanations for why this is happening. In terms of a workaround, I would probably add $a || $b || 1; after the use List::Util ... line. This would help to indicate why that code was there through association and would also remove the clutter of no warnings ... or our ... from the calls to reduce(). Furthermore, changes to code would not require any additional workaround changes. Here's some examples:

    $ perl -Mstrict -Mwarnings -E ' use List::Util qw/reduce/; say reduce { $a * $b } 1..6; ' Name "main::a" used only once: possible typo at -e line 3. Name "main::b" used only once: possible typo at -e line 3. 720
    $ perl -Mstrict -Mwarnings -E ' use List::Util qw/reduce/; $a || $b || 1; say reduce { $a * $b } 1..6; ' 720
    $ perl -Mstrict -Mwarnings -E ' use List::Util qw/reduce sum/; $a || $b || 1; say reduce { $a * $b } 1..6; say sum 1..6; ' 720 21

    -- Ken

Re: Name "main::a" used only once: possible typo
by subogero (Initiate) on Sep 12, 2017 at 15:56 UTC
    The best solution I found so far is this
    $SIG{__WARN__} = sub { my $w = shift; warn $w unless $w =~ /::[ab]" used only once:/; };
    EDIT: An even better one, preserving an already existing signal handler. It still does not guarantee ours won't be overwritten.
    my $orig_warn = $SIG{__WARN__}; $SIG{__WARN__} = $orig_warn ? sub { my $w = shift; $orig_warn->($w) if $w !~ /::[ab]" used onl +y once/ } : sub { my $w = shift; warn $w if $w !~ /::[ab]" used only once/ } +;
    EDIT: an even shorter one:
    my $abwarn = $SIG{__WARN__} // sub { warn shift }; $SIG{__WARN__} = sub { my $w = shift; $abwarn->($w) if $w !~ /::[ab]" used only once:/; };
Re: Name "main::a" used only once: possible typo
by mithaldu (Monk) on Mar 11, 2013 at 13:23 UTC
    I am confused that nobody suggested:

    print reduce { $_[0] * $_[1] } 1..6;
      Perhaps because it produces the incorrect result and 8 more warning messages:
      #!/usr/bin/env perl use warnings; use strict; use List::Util qw/reduce/; print reduce { $_[0] * $_[1] } 1..6; __END__ Use of uninitialized value in multiplication (*) at x.pl line 7. Use of uninitialized value in multiplication (*) at x.pl line 7. Use of uninitialized value in multiplication (*) at x.pl line 7. Use of uninitialized value in multiplication (*) at x.pl line 7. Use of uninitialized value in multiplication (*) at x.pl line 7. Use of uninitialized value in multiplication (*) at x.pl line 7. Use of uninitialized value in multiplication (*) at x.pl line 7. Use of uninitialized value in multiplication (*) at x.pl line 7. Use of uninitialized value in multiplication (*) at x.pl line 7. Use of uninitialized value in multiplication (*) at x.pl line 7. 0
      cause it doesn't work?

      use List::Util qw/reduce/; print reduce { $_[0] * $_[1] } 1..6; __END__ Use of uninitialized value in multiplication (*) at /home/lanx/B/PL/PM +/ScopeListUtils.pl line 23. ...

      Cheers Rolf

        Well damn. I was sure i had used that on List::Util stuff to get around $a/b warnings. Guess i misremembered.
      I guess List::Util::reduce does not pass the parameter pair at all to your function, it just localizes $a and $b with them.

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others exploiting the Monastery: (2)
As of 2024-03-19 06:11 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found