develooper Front page | perl.perl5.porters | Postings from August 2001

RE: [ID 20010813.010] List::Util::first fails on Array of Arrayrefs

From:
Wilson, Doug
Date:
August 14, 2001 15:06
Subject:
RE: [ID 20010813.010] List::Util::first fails on Array of Arrayrefs
Message ID:
35A280DF784CD411A06B0008C7B130ADB550ED@sdex04.sd.intuit.com

I've been trying to look into this, but XS is not my forte :(
Though I'm trying to learn :)

I originally found this problem on 5.6, but it still exists on
5.7.2, and List::Util is now in the core, so...

The problem as I've been able to distill it so far is on this code:
use strict;
use List::Util qw(first);

my @ary = ([qw(a b c)], [qw(d e f)], [qw(g h i)]);
my $foo = first { $_->[1] le "e" and "e" le $_->[2] } @ary;
print $foo->[0],"\n";

After the first call to CALLRUNOPS, the second argument on
the arg stack is clobbered, and so you get this error on the second call:
Can't use string ("2") as an ARRAY ref while "strict refs" in use at first.t
lin
e 8.

Just for kicks (since I don't really know what I'm doing yet),
I tried using SAVESPTR to save the stack arguments, and
got it working for this example, but then it broke just one of the existing
tests, specifically this one:
print "not " unless 9 == first { 8 == ($_ - 1) } 9,4,5,6;
print "ok 2\n";

although the above worked if I first saved the result of first()
to a temp variable and THEN compared it to 9.

Here is the entire first() code:
void
first(block,...)
    SV * block
PROTOTYPE: &@
CODE:
{
    int index;
    GV *gv;
    HV *stash;
    CV *cv;
    OP *reducecop;
    if(items <= 1) {
        XSRETURN_UNDEF;
    }
    SAVESPTR(GvSV(PL_defgv));
    cv = sv_2cv(block, &stash, &gv, 0);
    reducecop = CvSTART(cv);
    SAVESPTR(CvROOT(cv)->op_ppaddr);
    CvROOT(cv)->op_ppaddr = PL_ppaddr[OP_NULL];
    SAVESPTR(PL_curpad);
    PL_curpad = AvARRAY((AV*)AvARRAY(CvPADLIST(cv))[1]);
    SAVETMPS;
    SAVESPTR(PL_op);
    for(index = 1 ; index < items ; index++) {
        GvSV(PL_defgv) = ST(index);
        PL_op = reducecop;
        CALLRUNOPS(aTHX);
        if (SvTRUE(*PL_stack_sp)) {
          ST(0) = ST(index);
          XSRETURN(1);
        }
    }
    XSRETURN_UNDEF;
}

Help please? Thnxs,
Douglas Wilson



nntp.perl.org: Perl Programming lists via nntp and http.
Comments to Ask Bjørn Hansen at ask@perl.org | Group listing | About