Skip Menu |

This queue is for tickets about the List-MoreUtils CPAN distribution.

Report information
The Basics
Id: 76749
Status: resolved
Worked: 20 min
Priority: 0/
Queue: List-MoreUtils

People
Owner: Nobody in particular
Requestors: davido [...] cpan.org
Cc:
AdminCc:

Bug Information
Severity: Normal
Broken in: 0.33
Fixed in: (no value)



Subject: pairwise issues warnings about $a and $b being used only once.
Warnings should probably be suppressed regarding "used only once" for $a and $b within the code block of pairwise. Here is an example test that triggers two warnings: BEGIN{ $ENV{LIST_MOREUTILS_PP} = 1; } use strict; use warnings; use Test::More tests => 2; use Test::NoWarnings; use List::MoreUtils qw( pairwise ); diag "\n\$ENV{LIST_MOREUTILS_PP} = ", $ENV{LIST_MOREUTILS_PP}; diag 'List::MoreUtils version: ', $List::MoreUtils::VERSION, "\n\n"; { my @left = qw( one two three ); my @right = ( 1, 2, 3, ); my @res = pairwise { "$a => $b" } @left, @right; is( join( ' ', @res ), 'one => 1 two => 2 three => 3', "pairwise test." ); } Here is the output I get: 1..2 # # $ENV{LIST_MOREUTILS_PP} = 1 # List::MoreUtils version: 0.33 # ok 1 - pairwise test. not ok 2 - no warnings # Failed test 'no warnings' # at C:/strawberry/perl/vendor/lib/Test/NoWarnings.pm line 38. # There were 2 warning(s) # Previous test 0 '' # Name "main::b" used only once: possible typo at mytest.pl line 18. # at mytest.pl line 18 # # ---------- # Previous test 0 '' # Name "main::a" used only once: possible typo at mytest.pl line 18. # at mytest.pl line 18 # # Looks like you failed 1 test of 2. This may be an issue for other functions that also use $a and $b, though I didn't specifically test them too. Perl version 5.14.2. Tested on win32/strawberry, and Ubuntu Linux. Dave
I should mention that putting 'no warnings q(once);' at the beginning of pairwise code block squelches the warning, but it probably ought not be necessary to do so. my @res = pairwise { no warnings q(once); "$a => $b" } @left, @right;
Here is a patch that should resolve the warnings issue with as minimal impact as practical. diff --git a/lib/List/MoreUtils.pm b/lib/List/MoreUtils.pm index 676ebfd..d7fd12b 100644 --- a/lib/List/MoreUtils.pm +++ b/lib/List/MoreUtils.pm @@ -26,6 +26,14 @@ BEGIN { all => \@EXPORT_OK, ); + # Mention $a and $b within the caller's package to eliminate the + # "used only once" warnings. + { + no strict 'refs'; + ${caller().'::a'} = ${caller().'::a'}; + ${caller().'::b'} = ${caller().'::b'}; + } + # Load the XS at compile-time so that redefinition warnings will be # thrown correctly if the XS versions of part or indexes loaded eval { And here is a rewrite of the test I provided earlier. This version skips itself if Test::NoWarnings isn't installed, so that if it were to be added to the suite it wouldn't add a dependency requirement. use strict; use warnings; use Test::More; BEGIN { eval 'use Test::NoWarnings'; ## no critic (eval) plan( skip_all => "Test::NoWarnings required for pairwise warnings test" ) if $@; } plan tests => 2; use List::MoreUtils qw( pairwise ); # Using $a and $b in pairwise code blocks can result in a "used only once" # warning if the user only mentions $a and/or $b one time in the code block. # A patch was added after v0.33 to resolve the issue. # The pairwise test should pass regardless of the patch being applied. my @left = qw( one two three ); my @right = ( 1, 2, 3, ); my @res = pairwise { "$a => $b" } @left, @right; is( join( ' ', @res ), 'one => 1 two => 2 three => 3', "pairwise test." ); # The implicit Test::NoWarnings test will only pass with patch.
Uploaded the fix as RURBAN/List-MoreUtils-0.33_007.tar.gz -- Reini Urban
On Mon Dec 31 10:10:25 2012, RURBAN wrote: Show quoted text
> Uploaded the fix as RURBAN/List-MoreUtils-0.33_007.tar.gz
I'm now convinced that this patch only partially solves the problem. The correct approach is to touch $a and $b from within import() so that they're activated within the proper calling namespace. Here is a snippet from List::Util, which has fixed this problem: sub import { my $pkg = caller; # (RT88848) Touch the caller's $a and $b, to avoid the warning of # Name "main::a" used only once: possible typo" warning no strict 'refs'; ${"${pkg}::a"} = ${"${pkg}::a"}; ${"${pkg}::b"} = ${"${pkg}::b"}; goto &Exporter::import; } It might be better to instead goto SUPER::import, but that might just be nitpicking. Also, it's worth mentioning that $a and $b will probably be exempted from "used only once" warnings starting with Perl 5.20 anyway (https://rt.perl.org/Ticket/Display.html?id=120462). That being the case, it might be worthwhile doing the "touch $a and $b" dance only if $] < 5.020000.
I've added a test to current trunk but cannot reproduce the issue. If it's not gone, please come up with a test showing the warning.