This is something that's bothered me for awhile now, but until a few days ago I didn't take the time to investigate the "internals" involved.

Consider the following code:

use warnings; use List::Util; my $reduced = List::Util::reduce { $a + $b } 1, 2, 3, 4; print "$reduced\n";

This will generate the following output:

Name "main::a" used only once: possible typo at mytest.pl line 3. Name "main::b" used only once: possible typo at mytest.pl line 3. 10

On the other hand...

use warnings; my @sorted = sort { $a <=> $b } 1, 2, 3, 4; print "@sorted\n";

...will produce...

1 2 3 4

Given that List::Util is a core module, reduce really ought to have the same privileges as sort with respect to gracefully using $a and $b. I looked at what makes sort's code different from reduce, aside from the obvious fact that one sorts and one reduces. I began by trying to find two needles in the Perl code-base haystack (searching for a and b doesn't really narrow it down). tye was helpful in pointing me to some code in op.c.

This seems to be the relevant segment:

STATIC void S_simplify_sort(pTHX_ OP *o) { dVAR; OP *kid = cLISTOPo->op_first->op_sibling; /* get past pushmark +*/ OP *k; int descending; GV *gv; const char *gvname; bool have_scopeop; PERL_ARGS_ASSERT_SIMPLIFY_SORT; if (!(o->op_flags & OPf_STACKED)) return; GvMULTI_on(gv_fetchpvs("a", GV_ADD|GV_NOTQUAL, SVt_PV)); GvMULTI_on(gv_fetchpvs("b", GV_ADD|GV_NOTQUAL, SVt_PV)); ...

GvMULTI_on must have the effect of tricking Perl into thinking that $a and $b were already used more than once, which takes care of the warning. perlguts, says this in reference to to the SV*  get_sv("package::varname", GV_ADD); function:

There are additional macros whose values may be bitwise OR'ed with the GV_ADD argument to enable certain extra features. Those bits are:

GV_ADDMULTI
Marks the variable as multiply defined, thus preventing the:
  Name <varname> used only once: possible typo
warning.

I thought maybe just using GV_ADD|GV_ADDMULTI could have the same effect without an explicit call to the undocumented GvMULTI_on().

Then I looked at the relevant code in List::Utils:

void reduce(block,...) SV * block PROTOTYPE: &@ CODE: { SV *ret = sv_newmortal(); int index; GV *agv,*bgv,*gv; HV *stash; SV **args = &PL_stack_base[ax]; CV* cv = sv_2cv(block, &stash, &gv, 0); if (cv == Nullcv) { croak("Not a subroutine reference"); } if(items <= 1) { XSRETURN_UNDEF; } agv = gv_fetchpv("a", GV_ADD, SVt_PV); bgv = gv_fetchpv("b", GV_ADD, SVt_PV); ...

Ah-hah! Add a call to GvMULTI_on(), or "or"-ing (|) GV_ADDMULTI into the fetch, should yield a patch for reduce that allows it to play nice with warnings.

agv = gv_fetchpv("a", GV_ADD, SVt_PV); GvMULTI_on(agv); /* No apparent effect. */ agv = gv_fetchpv("a", GV_ADD|GV_ADDMULTI, SVt_PV); /* Nope */ agv = gv_fetchpv("a", GV_ADDMULTI, SVt_PV); /* *sigh* No. */

Which brings me here to the font of Perl wisdom, hoping someone can explain why, why not, and possibly what needs to happen (in the module or perl) to solve it. This would also help to settle the same bug in List::MoreUtils::pairwise, as well as helping me out with a pet project.

Can anyone shed some light?

Update: I'm aware of many of the previous conversations on the topic. I'm looking at this from an internals perspective; what can the XS code of these modules do to eliminate the problem, not how can I make my use of these modules not trigger warnings. Actually, BrowserUk may be on to something... time for more tests. ;)


Dave


In reply to Eliminating "used only once" warnings from List::Util::reduce by davido

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.