Array::Each::Override - C<each> for iterating over an array's keys and values


Array-Each-Override documentation Contained in the Array-Each-Override distribution.

Index


Code Index:

NAME

Top

Array::Each::Override - each for iterating over an array's keys and values

SYNOPSIS

Top

    use Array::Each::Override;

    my @array = get_data();
    while (my ($i, $val) = each @array) {
        print "Position $i contains: $val\n";
    }

DESCRIPTION

Top

This module provides new implementations of three core functions: each, values, and keys.

each

The core each function iterates over a hash; each time it's called, it returns a 2-element list of a key and value in the hash. The new version of each does not change the behaviour of each when called on a hash. However, it also allows you to call each on array. Each time it's called, it returns a 2-element list of the next uniterated index in the the array, and the value at that index.

When the array is entirely iterated, an empty list is returned in list context. The next call to array each after that will start iterating again.

keys

The core keys function returns a list of the keys in a hash, or a count of the keys in a hash when called in scalar context. The new version of keys does not change the behaviour of keys when called on a hash. However, it also allows you to call keys on an array.

In list context, keys @array returns a list of the indexes in the array; in scalar context, it returns the number of elements in the array.

values

The core values function returns a list of the values in a hash, or a count of the values in a hash when called in scalar context. The new version of values does not change the behaviour of values when called on a hash. However, it also allows you to call values on an array.

In list context, values @array returns a list of the elements in the array; in scalar context, it returns the number of elements in the array.

There is a single iterator for each array, shared by all each, keys, and values calls in the program. It can be reset by reading all the elements from the iterator with each, or by evaluating keys @array or values @array.

ALTERNATIVE NAMES

Top

You may prefer not to change the core each, keys, and values functions. If so, you can import the new functions under alternative, noninvasive names:

    use Array::Each::Override qw<array_each array_keys array_values>;

Or to import all of them in one go:

    use Array::Each::Override qw<:safe>;

Or mix and match:

    use Array::Each::Override qw<each array_keys array_values>;

The functions with these noninvasive names behave exactly the same as the overridden core functions.

You might alternatively prefer to make the new functions available to all parts of your program in one fell swoop:

    use Array::Each::Override qw<:global>;

Or make just some of the functions global:

    use Array::Each::Override qw<:global each keys>;

You can also unimport names. For example, this removes the globally overridden functions:

    no Array::Each::Override qw<:global>;

BUGS

Top

PERFORMANCE

Top

There is some overhead for calling the new functions on a hash, compared to the standard core functions. The approximate penalties in each case are as follows:

each %hash

20-25%

scalar-context keys %hash

55-60%

scalar-context values %hash

60-65%

list-context keys %hash

1%

list-context values %hash

1%

If this performance penalty bothers you, use the :safe function names instead.

SEE ALSO

Top

perlfunc (each), perlfunc (keys), perlfunc (values).

AUTHOR

Top

Aaron Crane <arc@cpan.org>

Thanks to Chia-Liang Kao for his help in getting this working.

COPYRIGHT

Top


Array-Each-Override documentation Contained in the Array-Each-Override distribution.

package Array::Each::Override;

use strict;
use warnings;

our $VERSION = '0.04';
use base qw<DynaLoader>;

use Scalar::Util qw<reftype>;
use Carp qw<croak>;

my @FUNCTIONS = qw<each keys values>;
my %KNOWN_FUNCTION = map { ($_ => 1, "array_$_" => 1) } @FUNCTIONS;

__PACKAGE__->bootstrap($VERSION);

sub import {
    my ($class, @imports) = @_;
    my $caller = caller;
    for my $export (_parse_import_list($caller, @imports)) {
        my ($dest, $name, $func) = @$export{qw<dest name func>};
        no strict qw<refs>;
        *{"$dest\::$name"} = $func;
    }
}

sub unimport {
    my ($package, @imports) = @_;
    my $caller = caller;
    for my $export (_parse_import_list($caller, @imports)) {
        my ($dest, $name, $func) = @$export{qw<dest name func>};
        no strict qw<refs>;
        delete ${"$dest\::"}{$name}
    }
}

sub _parse_import_list {
    my ($importer, @imports) = @_;

    for my $name (@imports) {
        croak "Unknown function '$name'"
            if !$KNOWN_FUNCTION{$name}
            && $name ne ':global'
            && $name ne ':safe';
    }

    my $mode = '';
    $mode = shift @imports
        if @imports && $imports[0] =~ /\A :/xms;

    croak ":global or :safe must be the first item in the import list"
        if grep { /^:/ } @imports;

    @imports = @FUNCTIONS if !@imports;

    $importer = 'CORE::GLOBAL'
        if $mode eq ':global';

    return map {
        (my $func_name = $_) =~ s/\A (?!array_)/array_/xms;
        $_ = $func_name if $mode eq ':safe';
        my $func = do { no strict 'refs'; \&$func_name };
        +{
            dest => $importer,
            func => $func,
            name => $_,
        };
    } @imports;
}

1;