Приглашаем посетить
Татищев (tatischev.lit-info.ru)

Section 4.18.  List Membership

Previous
Table of Contents
Next

4.18. List Membership

Use table-lookup to test for membership in lists of strings; use any( ) for membership of lists of anything else.

Like grep, the any( ) function from List::MoreUtils (see "Utilities" in Chapter 8) takes a block of code followed by a list of values. Like grep, it applies the code block to each value in turn, passing them as $_. But, unlike grep, any( ) returns a true value as soon as any of the values causes its test block to succeed. If none of the values ever makes the block true, any( ) returns false.

This behaviour makes any( ) an efficient general solution for testing list membership, because you can put any kind of equivalence test in the block. For example:


    
# Is the index number already taken?
if ( any { $requested_slot == $_ } @allocated_slots ) { print "Slot $requested_slot is already taken. Please select another: "; redo GET_SLOT; }

or:


    
# Is the bad guy at the party under an assumed name?
if ( any { $fugitive->also_known_as($_) } @guests ) { stay_calm( ); dial(911); do_not_approach($fugitive); }

But don't use any( ) if your list membership test uses eq:

    Readonly my @EXIT_WORDS => qw(
        q  quit  bye  exit  stop  done  last  finish  aurevoir
    );

    # and later...

    if ( any { $cmd eq $_ } @EXIT_WORDS ) {
        abort_run( );
    }

In such cases it's much better to use a look-up table instead:


    Readonly my %IS_EXIT_WORD
        => map { ($_ => 1) } qw(
               q  quit  bye  exit  stop  done  last  finish  aurevoir
           );

    
# and later...
if ( $IS_EXIT_WORD{$cmd} ) { abort_run( ); }

The hash access is faster than a linear search through an array, even if that search can short-circuit. The code implementing the test is far more readable as well.

    Previous
    Table of Contents
    Next