X-Git-Url: https://perl5.git.perl.org/perl5.git/blobdiff_plain/d81c2d6ac7251c7a671bffcafe3dbcf20a83bb8a..060e131ef7ef9bfe80a0751328042b9d1ae24139:/cpan/Scalar-List-Utils/lib/List/Util.pm diff --git a/cpan/Scalar-List-Utils/lib/List/Util.pm b/cpan/Scalar-List-Utils/lib/List/Util.pm index 9296221..4a03af8 100644 --- a/cpan/Scalar-List-Utils/lib/List/Util.pm +++ b/cpan/Scalar-List-Utils/lib/List/Util.pm @@ -7,14 +7,15 @@ package List::Util; use strict; +use warnings; require Exporter; our @ISA = qw(Exporter); our @EXPORT_OK = qw( - all any first min max minstr maxstr none notall product reduce sum sum0 shuffle - pairmap pairgrep pairfirst pairs pairkeys pairvalues + all any first min max minstr maxstr none notall product reduce sum sum0 shuffle uniq uniqnum uniqstr + pairs unpairs pairkeys pairvalues pairmap pairgrep pairfirst ); -our $VERSION = "1.40"; +our $VERSION = "1.48"; our $XS_VERSION = $VERSION; $VERSION = eval $VERSION; @@ -38,17 +39,21 @@ sub import sub List::Util::_Pair::key { shift->[0] } sub List::Util::_Pair::value { shift->[1] } -1; - -__END__ - =head1 NAME List::Util - A selection of general-utility list subroutines =head1 SYNOPSIS - use List::Util qw(first max maxstr min minstr reduce shuffle sum); + use List::Util qw( + reduce any all none notall first + + max maxstr min minstr product sum sum0 + + pairs unpairs pairkeys pairvalues pairfirst pairgrep pairmap + + shuffle uniq uniqnum uniqstr + ); =head1 DESCRIPTION @@ -67,7 +72,9 @@ The following set of functions all reduce a list down to a single value. =cut -=head2 $result = reduce { BLOCK } @list +=head2 reduce + + $result = reduce { BLOCK } @list Reduces C<@list> by calling C in a scalar context multiple times, setting C<$a> and C<$b> each time. The first call will be with C<$a> and C<$b> @@ -107,6 +114,20 @@ C being returned $foo = reduce { $a + $b } 0, @values; # sum with 0 identity value +The above example code blocks also suggest how to use C to build a +more efficient combined version of one of these basic functions and a C +block. For example, to find the total length of the all the strings in a list, +we could use + + $total = sum map { length } @strings; + +However, this produces a list of temporary integer values as long as the +original list of strings, only to reduce it down to a single value again. We +can compute the same result more efficiently by using C with a code +block that accumulates lengths by writing this instead as: + + $total = reduce { $a + length $b } 0, @strings + The remaining list-reduction functions are all specialisations of this generic idea. @@ -128,6 +149,9 @@ instead, as it can short-circuit after the first true result. # at least one string has more than 10 characters } +Note: Due to XS issues the block passed may be able to access the outer @_ +directly. This is not intentional and will break under debugger. + =head2 all my $bool = all { BLOCK } @list; @@ -139,6 +163,9 @@ make the C return true. If any element returns false, then it returns false. If the C never returns false or the C<@list> was empty then it returns true. +Note: Due to XS issues the block passed may be able to access the outer @_ +directly. This is not intentional and will break under debugger. + =head2 none =head2 notall @@ -153,6 +180,9 @@ Similar to L and L, but with the return sense inverted. C returns true only if no value in the C<@list> causes the C to return true, and C returns true only if not all of the values do. +Note: Due to XS issues the block passed may be able to access the outer @_ +directly. This is not intentional and will break under debugger. + =head2 first my $val = first { BLOCK } @list; @@ -254,8 +284,120 @@ or just a list of values. The functions will all preserve the original ordering of the pairs, and will not be confused by multiple pairs having the same "key" value - nor even do they require that the first of each pair be a plain string. +B: At the time of writing, the following C functions that take a +block do not modify the value of C<$_> within the block, and instead operate +using the C<$a> and C<$b> globals instead. This has turned out to be a poor +design, as it precludes the ability to provide a C function. Better +would be to pass pair-like objects as 2-element array references in C<$_>, in +a style similar to the return value of the C function. At some future +version this behaviour may be added. + +Until then, users are alerted B to rely on the value of C<$_> remaining +unmodified between the outside and the inside of the control block. In +particular, the following example is B: + + my @kvlist = ... + + foreach (qw( some keys here )) { + my @items = pairgrep { $a eq $_ } @kvlist; + ... + } + +Instead, write this using a lexical variable: + + foreach my $key (qw( some keys here )) { + my @items = pairgrep { $a eq $key } @kvlist; + ... + } + =cut +=head2 pairs + + my @pairs = pairs @kvlist; + +I + +A convenient shortcut to operating on even-sized lists of pairs, this function +returns a list of C references, each containing two items from the +given list. It is a more efficient version of + + @pairs = pairmap { [ $a, $b ] } @kvlist + +It is most convenient to use in a C loop, for example: + + foreach my $pair ( pairs @kvlist ) { + my ( $key, $value ) = @$pair; + ... + } + +Since version C<1.39> these C references are blessed objects, +recognising the two methods C and C. The following code is +equivalent: + + foreach my $pair ( pairs @kvlist ) { + my $key = $pair->key; + my $value = $pair->value; + ... + } + +=head2 unpairs + + my @kvlist = unpairs @pairs + +I + +The inverse function to C; this function takes a list of C +references containing two elements each, and returns a flattened list of the +two values from each of the pairs, in order. This is notionally equivalent to + + my @kvlist = map { @{$_}[0,1] } @pairs + +except that it is implemented more efficiently internally. Specifically, for +any input item it will extract exactly two values for the output list; using +C if the input array references are short. + +Between C and C, a higher-order list function can be used to +operate on the pairs as single scalars; such as the following near-equivalents +of the other C higher-order functions: + + @kvlist = unpairs grep { FUNC } pairs @kvlist + # Like pairgrep, but takes $_ instead of $a and $b + + @kvlist = unpairs map { FUNC } pairs @kvlist + # Like pairmap, but takes $_ instead of $a and $b + +Note however that these versions will not behave as nicely in scalar context. + +Finally, this technique can be used to implement a sort on a keyvalue pair +list; e.g.: + + @kvlist = unpairs sort { $a->key cmp $b->key } pairs @kvlist + +=head2 pairkeys + + my @keys = pairkeys @kvlist; + +I + +A convenient shortcut to operating on even-sized lists of pairs, this function +returns a list of the the first values of each of the pairs in the given list. +It is a more efficient version of + + @keys = pairmap { $a } @kvlist + +=head2 pairvalues + + my @values = pairvalues @kvlist; + +I + +A convenient shortcut to operating on even-sized lists of pairs, this function +returns a list of the the second values of each of the pairs in the given list. +It is a more efficient version of + + @values = pairmap { $b } @kvlist + =head2 pairgrep my @kvlist = pairgrep { BLOCK } @kvlist; @@ -329,71 +471,85 @@ will be visible to the caller. See L for a known-bug with C, and a workaround. -=head2 pairs +=cut - my @pairs = pairs @kvlist; +=head1 OTHER FUNCTIONS -I +=cut -A convenient shortcut to operating on even-sized lists of pairs, this function -returns a list of ARRAY references, each containing two items from the given -list. It is a more efficient version of +=head2 shuffle - @pairs = pairmap { [ $a, $b ] } @kvlist + my @values = shuffle @values; -It is most convenient to use in a C loop, for example: +Returns the values of the input in a random order - foreach my $pair ( pairs @KVLIST ) { - my ( $key, $value ) = @$pair; - ... - } + @cards = shuffle 0..51 # 0..51 in a random order -Since version C<1.39> these ARRAY references are blessed objects, recognising -the two methods C and C. The following code is equivalent: +=head2 uniq - foreach my $pair ( pairs @KVLIST ) { - my $key = $pair->key; - my $value = $pair->value; - ... - } + my @subset = uniq @values -=head2 pairkeys +I - my @keys = pairkeys @kvlist; +Filters a list of values to remove subsequent duplicates, as judged by a +DWIM-ish string equality or C test. Preserves the order of unique +elements, and retains the first value of any duplicate set. -I + my $count = uniq @values -A convenient shortcut to operating on even-sized lists of pairs, this function -returns a list of the the first values of each of the pairs in the given list. -It is a more efficient version of +In scalar context, returns the number of elements that would have been +returned as a list. - @keys = pairmap { $a } @kvlist +The C value is treated by this function as distinct from the empty +string, and no warning will be produced. It is left as-is in the returned +list. Subsequent C values are still considered identical to the first, +and will be removed. -=head2 pairvalues +=head2 uniqnum - my @values = pairvalues @kvlist; + my @subset = uniqnum @values -I +I -A convenient shortcut to operating on even-sized lists of pairs, this function -returns a list of the the second values of each of the pairs in the given list. -It is a more efficient version of +Filters a list of values to remove subsequent duplicates, as judged by a +numerical equality test. Preserves the order of unique elements, and retains +the first value of any duplicate set. - @values = pairmap { $b } @kvlist + my $count = uniqnum @values -=cut +In scalar context, returns the number of elements that would have been +returned as a list. -=head1 OTHER FUNCTIONS +Note that C is treated much as other numerical operations treat it; it +compares equal to zero but additionally produces a warning if such warnings +are enabled (C). In addition, an C in +the returned list is coerced into a numerical zero, so that the entire list of +values returned by C are well-behaved as numbers. -=cut +Note also that multiple IEEE C values are treated as duplicates of +each other, regardless of any differences in their payloads, and despite +the fact that C<< 0+'NaN' == 0+'NaN' >> yields false. -=head2 shuffle +=head2 uniqstr - my @values = shuffle @values; + my @subset = uniqstr @values -Returns the values of the input in a random order +I - @cards = shuffle 0..51 # 0..51 in a random order +Filters a list of values to remove subsequent duplicates, as judged by a +string equality test. Preserves the order of unique elements, and retains the +first value of any duplicate set. + + my $count = uniqstr @values + +In scalar context, returns the number of elements that would have been +returned as a list. + +Note that C is treated much as other string operations treat it; it +compares equal to the empty string but additionally produces a warning if such +warnings are enabled (C). In addition, an +C in the returned list is coerced into an empty string, so that the +entire list of values returned by C are well-behaved as strings. =cut @@ -442,6 +598,21 @@ afterwards. Lexical variables that are only used during the lifetime of the block's execution will take their individual values for each invocation, as normal. +=head2 uniqnum() on oversized bignums + +Due to the way that C compares numbers, it cannot distinguish +differences between bignums (especially bigints) that are too large to fit in +the native platform types. For example, + + my $x = Math::BigInt->new( "1" x 100 ); + my $y = $x + 1; + + say for uniqnum( $x, $y ); + +Will print just the value of C<$x>, believing that C<$y> is a numerically- +equivalent value. This bug does not affect C, which will correctly +observe that the two values stringify to different strings. + =head1 SUGGESTED ADDITIONS The following are additions that have been requested, but I have been reluctant @@ -469,3 +640,5 @@ Recent additions and current maintenance by Paul Evans, . =cut + +1;