pairwise_test

D

Dr.Ruud

Inspired by List::MoreUtils, I came up with the following.
Please comment on the name of the sub, and on any problems
you see, and on what not.

#!/usr/bin/perl
use strict;
use warnings;

# pairwise_firstidx BLOCK ARRAY1 ARRAY2

  • # returns the first index for which the BLOCK returns a defined value,
    # optionally only for a list of index values

    sub pairwise_do (&\@\@;@)
    {
    use vars qw/$a $b/;
    my $op = shift; # the BLOCK

    my ($caller_a, $caller_b) = do
    { my $pkg = caller();
    no strict 'refs';
    \*{$pkg.'::a'}, \*{$pkg.'::b'};
    };

    my $retval;
    local (*$caller_a, *$caller_b);

    for ( $_[2]
    ?
    @_[2..$#_]
    :
    $[ .. $#{$_[0]} >= $#{$_[1]}
    ?
    $#{$_[0]}
    :
    $#{$_[1]}
    ) {
    (*$caller_a, *$caller_b) = \($_[0][$_], $_[1][$_]);
    defined ($retval = $op->()) and return $retval;
    }
    return;
    }

    my @x = (0..6, 70..99);
    my @y = (0..6, 80..99);

    # find the index of the first non-equal value for
    # two arrays, and within a specific index range:
    print pairwise_do { $a != $b ? $_ : undef } @x, @y, 2..9;


    __END__
 
B

Brian McCauley

Inspired by List::MoreUtils, I came up with the following.
Please comment on the name of the sub, and on any problems
you see, and on what not.
# pairwise_firstidx BLOCK ARRAY1 ARRAY2

  • # returns the first index for which the BLOCK returns a defined
    # value,


  • Well, there's your first problem. It doesn't return the index. It
    returns the return value of the block.
 
D

Dr.Ruud

Brian McCauley schreef:
Dr.Ruud:
Inspired by List::MoreUtils, I came up with the following.
Please comment on the name of the sub, and on any problems
you see, and on what not.
# pairwise_firstidx BLOCK ARRAY1 ARRAY2

  • # returns the first index for which the BLOCK returns a defined
    # value,


  • Well, there's your first problem. It doesn't return the index. It
    returns the return value of the block.
    defined ($retval = $op->()) and return $retval;


  • Ah yes, the documentation is outdated. And with that the name of the
    function is wrong. (Or I made it too versatile.)

    The BLOCK can return the index value through $_. I see that as the
    normal usage, but other usage is not discouraged.

    Maybe 'pairwise_do' is a better function name?

    What is the next problem?
 
M

Michele Dondi

# find the index of the first non-equal value for
# two arrays, and within a specific index range:
print pairwise_do { $a != $b ? $_ : undef } @x, @y, 2..9;

Maybe useful for other purposes, but in this case, what's the *big*
advantage over List::Util's

print first { $x[$_] != $y[$_] } 2..9; # ?

If the range were not explicit... then yes, somewhat more clumsy:

print first { $x[$_] != $y[$_] } 1..max($#x,$#y);

However what one feels more missing in Perl 5 is probably a way to do
things in a parallel manner on two or more lists. That's what Perl 6
zip operator and new pointy subs are really great for:

for @x Z @y -> $a, $b { say "<$a> <$b>" if $a !$ $b}

(Don't know 'bout map() & C. - I'm really a baby-Perl-6'er)


Michele
 
D

Dr.Ruud

Michele Dondi schreef:
Dr.Ruud:
# find the index of the first non-equal value for
# two arrays, and within a specific index range:
print pairwise_do { $a != $b ? $_ : undef } @x, @y, 2..9;

Maybe useful for other purposes, but in this case, what's the
*big* advantage over List::Util's

print first { $x[$_] != $y[$_] } 2..9; # ?

Thanks, that is a good alternative for this case. I'll check out the
implementation of first() too.

I want mine to be shortcutting, as first() most probably is too.
And to work on defined() in stead of true/false, so maybe I should call
it first_defined(). Or change to true/false.

A variant of List::MoreUtils::firstidx() could look like this:

$i = firstidx { $a != $b } @x, @y;
$i = firstidx { $a != $b } @x, @y, 2..9;

I'll try to come up with an example that uses it more to the full, I
need to write tests anyway.

If the range were not explicit... then yes, somewhat more clumsy:

print first { $x[$_] != $y[$_] } 1..max($#x,$#y);

ITYM 0 .. max($#x,$#y).
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,055
Latest member
SlimSparkKetoACVReview

Latest Threads

Top