21

The List::MoreUtils module indicates that you use the variables $a and $b when supplying the BLOCK that goes with the pairwise function. For example:

use strict;
use warnings;
use List::MoreUtils qw'pairwise';

my @x = ( 1 ..  5);
my @y = (11 .. 15);
my @sums = pairwise { $a + $b } @x, @y;

But when I do that, I get warnings like this:

Name "main::b" used only once: possible typo at try.pl line 7.
Name "main::a" used only once: possible typo at try.pl line 7.

Is there an elegant way to deal with this problem?

Update:

See the answer by Ether for perl v5.19.6 and beyond: problem solved.

Community
  • 1
  • 1
FMc
  • 41,963
  • 13
  • 79
  • 132
  • 1
    This didn't appear to have been reported previously, so I have just done so at https://rt.cpan.org/Ticket/Display.html?id=65629 – Ether Feb 10 '11 at 21:26

6 Answers6

24

Depends on what you consider elegant.

no warnings qw(once);
our ($a, $b);

One of these two will suffice. You can even limit their scope pretty easily.

my @sums = pairwise { no warnings qw(once); $a + $b } @x, @y;
my @sums = pairwise { our $a + our $b } @x, @y;

Explicitly specifying the package will suppress the warning too. If you're in main,

my @sums = pairwise { $::a + $::b } @x, @y;
ephemient
  • 198,619
  • 38
  • 280
  • 391
  • This "no warnings" is not necessary - at least in first example. –  Sep 29 '09 at 05:03
  • 3
    If I may quote the line following that code, "One of these two will suffice." – Chris Lutz Sep 29 '09 at 05:08
  • @Chris Lutz: sorry, my misunderstanding. –  Sep 29 '09 at 08:52
  • @ephemient Thanks for the response. The last option (specifying the full package) did not eliminate the warning in my example. – FMc Sep 29 '09 at 13:43
  • Hmm, it eliminates the warning for me with Perl 5.10.0 (without any `use feature`). Well, I prefer the `our` method anyhow... – ephemient Sep 29 '09 at 14:21
7

Yep, it's not you. You can no warnings 'once'; or you can predeclare $a and $b so that they will not be used once anymore.

our ($a, $b);

does the trick. I tend to prefer that because it doesn't turn off warnings for anything else, and it's a bit more descriptive.

masonk
  • 9,176
  • 2
  • 47
  • 58
6

This is probably a bug in List::Util.

Turning off warnings globally is probably not a good idea, however you could do something like this:

{
  no warnings 'once';
  return join("_", @monsters) if @monsters && List::Util::reduce { $a && $b // 0 > 0 } 1,@monsters;
}

This would turn off the relevant warning category for that part of the code only.

szbalint
  • 1,643
  • 12
  • 20
5

As of perl 5.19.6, this warning is disabled for all uses of $a and $b everywhere.

Ether
  • 53,118
  • 13
  • 86
  • 159
2

Add this near top of your program:

use vars qw( $a $b );

or, if you don't like the "obsolete" part of perldoc vars, simply add:

our ( $a, $b );
  • I remember somewhere reading that `use vars qw($a $b);` messed with `sort()` but I can't seem to find it in perldoc, so it may just be a figment of my imagination. – Chris Lutz Sep 29 '09 at 05:06
  • 3
    `use vars` is package-scoped while `our` is lexically scoped to the containing block, so from the point of environmental sanitation, I prefer `our`... – ephemient Sep 29 '09 at 14:24
1

I have the same problem with a similar module I'm writing. The only solution I've found (other than using functions that use $a and $b twice, of course) is to put this line somewhere in your code:

$a = $b; # hack to disable warnings about "main::a" used only once

It basically does nothing, but it does disable the warning. Consider keeping the comment so future maintainers don't have to read your mind.

Chris Lutz
  • 73,191
  • 16
  • 130
  • 183
  • I guess you meant `$a = $a` :) – pwes Jul 01 '11 at 19:18
  • 2
    @pwes - Nope. It's been a while but IIRC it gives the warning about both `$a` and `$b`. `$a = $b` neatly uses both, thus disabling warnings about each of them. Though it is possible that either one could have a value left over from a `BEGIN` block, and the later code _could_ rely on this value (though the thought gives me nightmares), so `$a = $a; $b = $b;` might technically be better. – Chris Lutz Jul 01 '11 at 20:32
  • OK, I thought you meant to use it inside the block -- in which case it _does_ something :) – pwes Aug 05 '11 at 09:38