This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Refactoring to Sv*_set() macros - patch #5
[perl5.git] / ext / List / Util / lib / List / Util.pm
1 # List::Util.pm
2 #
3 # Copyright (c) 1997-2004 Graham Barr <gbarr@pobox.com>. All rights reserved.
4 # This program is free software; you can redistribute it and/or
5 # modify it under the same terms as Perl itself.
6
7 package List::Util;
8
9 require Exporter;
10
11 @ISA        = qw(Exporter);
12 @EXPORT_OK  = qw(first min max minstr maxstr reduce sum shuffle);
13 $VERSION    = "1.14_01";
14 $XS_VERSION = $VERSION;
15 $VERSION    = eval $VERSION;
16
17 eval {
18   # PERL_DL_NONLAZY must be false, or any errors in loading will just
19   # cause the perl code to be tested
20   local $ENV{PERL_DL_NONLAZY} = 0 if $ENV{PERL_DL_NONLAZY};
21   require DynaLoader;
22   local @ISA = qw(DynaLoader);
23   bootstrap List::Util $XS_VERSION;
24   1
25 };
26
27 eval <<'ESQ' unless defined &reduce;
28
29 # This code is only compiled if the XS did not load
30
31 use vars qw($a $b);
32
33 sub reduce (&@) {
34   my $code = shift;
35
36   return shift unless @_ > 1;
37
38   my $caller = caller;
39   local(*{$caller."::a"}) = \my $a;
40   local(*{$caller."::b"}) = \my $b;
41
42   $a = shift;
43   foreach (@_) {
44     $b = $_;
45     $a = &{$code}();
46   }
47
48   $a;
49 }
50
51 sub sum (@) { reduce { $a + $b } @_ }
52
53 sub min (@) { reduce { $a < $b ? $a : $b } @_ }
54
55 sub max (@) { reduce { $a > $b ? $a : $b } @_ }
56
57 sub minstr (@) { reduce { $a lt $b ? $a : $b } @_ }
58
59 sub maxstr (@) { reduce { $a gt $b ? $a : $b } @_ }
60
61 sub first (&@) {
62   my $code = shift;
63
64   foreach (@_) {
65     return $_ if &{$code}();
66   }
67
68   undef;
69 }
70
71 sub shuffle (@) {
72   my @a=\(@_);
73   my $n;
74   my $i=@_;
75   map {
76     $n = rand($i--);
77     (${$a[$n]}, $a[$n] = $a[$i])[0];
78   } @_;
79 }
80
81 ESQ
82
83 1;
84
85 __END__
86
87 =head1 NAME
88
89 List::Util - A selection of general-utility list subroutines
90
91 =head1 SYNOPSIS
92
93     use List::Util qw(first max maxstr min minstr reduce shuffle sum);
94
95 =head1 DESCRIPTION
96
97 C<List::Util> contains a selection of subroutines that people have
98 expressed would be nice to have in the perl core, but the usage would
99 not really be high enough to warrant the use of a keyword, and the size
100 so small such that being individual extensions would be wasteful.
101
102 By default C<List::Util> does not export any subroutines. The
103 subroutines defined are
104
105 =over 4
106
107 =item first BLOCK LIST
108
109 Similar to C<grep> in that it evaluates BLOCK setting C<$_> to each element
110 of LIST in turn. C<first> returns the first element where the result from
111 BLOCK is a true value. If BLOCK never returns true or LIST was empty then
112 C<undef> is returned.
113
114     $foo = first { defined($_) } @list    # first defined value in @list
115     $foo = first { $_ > $value } @list    # first value in @list which
116                                           # is greater than $value
117
118 This function could be implemented using C<reduce> like this
119
120     $foo = reduce { defined($a) ? $a : wanted($b) ? $b : undef } undef, @list
121
122 for example wanted() could be defined() which would return the first
123 defined value in @list
124
125 =item max LIST
126
127 Returns the entry in the list with the highest numerical value. If the
128 list is empty then C<undef> is returned.
129
130     $foo = max 1..10                # 10
131     $foo = max 3,9,12               # 12
132     $foo = max @bar, @baz           # whatever
133
134 This function could be implemented using C<reduce> like this
135
136     $foo = reduce { $a > $b ? $a : $b } 1..10
137
138 =item maxstr LIST
139
140 Similar to C<max>, but treats all the entries in the list as strings
141 and returns the highest string as defined by the C<gt> operator.
142 If the list is empty then C<undef> is returned.
143
144     $foo = maxstr 'A'..'Z'          # 'Z'
145     $foo = maxstr "hello","world"   # "world"
146     $foo = maxstr @bar, @baz        # whatever
147
148 This function could be implemented using C<reduce> like this
149
150     $foo = reduce { $a gt $b ? $a : $b } 'A'..'Z'
151
152 =item min LIST
153
154 Similar to C<max> but returns the entry in the list with the lowest
155 numerical value. If the list is empty then C<undef> is returned.
156
157     $foo = min 1..10                # 1
158     $foo = min 3,9,12               # 3
159     $foo = min @bar, @baz           # whatever
160
161 This function could be implemented using C<reduce> like this
162
163     $foo = reduce { $a < $b ? $a : $b } 1..10
164
165 =item minstr LIST
166
167 Similar to C<min>, but treats all the entries in the list as strings
168 and returns the lowest string as defined by the C<lt> operator.
169 If the list is empty then C<undef> is returned.
170
171     $foo = minstr 'A'..'Z'          # 'A'
172     $foo = minstr "hello","world"   # "hello"
173     $foo = minstr @bar, @baz        # whatever
174
175 This function could be implemented using C<reduce> like this
176
177     $foo = reduce { $a lt $b ? $a : $b } 'A'..'Z'
178
179 =item reduce BLOCK LIST
180
181 Reduces LIST by calling BLOCK multiple times, setting C<$a> and C<$b>
182 each time. The first call will be with C<$a> and C<$b> set to the first
183 two elements of the list, subsequent calls will be done by
184 setting C<$a> to the result of the previous call and C<$b> to the next
185 element in the list.
186
187 Returns the result of the last call to BLOCK. If LIST is empty then
188 C<undef> is returned. If LIST only contains one element then that
189 element is returned and BLOCK is not executed.
190
191     $foo = reduce { $a < $b ? $a : $b } 1..10       # min
192     $foo = reduce { $a lt $b ? $a : $b } 'aa'..'zz' # minstr
193     $foo = reduce { $a + $b } 1 .. 10               # sum
194     $foo = reduce { $a . $b } @bar                  # concat
195
196 =item shuffle LIST
197
198 Returns the elements of LIST in a random order
199
200     @cards = shuffle 0..51      # 0..51 in a random order
201
202 =item sum LIST
203
204 Returns the sum of all the elements in LIST.
205
206     $foo = sum 1..10                # 55
207     $foo = sum 3,9,12               # 24
208     $foo = sum @bar, @baz           # whatever
209
210 This function could be implemented using C<reduce> like this
211
212     $foo = reduce { $a + $b } 1..10
213
214 =back
215
216 =head1 KNOWN BUGS
217
218 With perl versions prior to 5.005 there are some cases where reduce
219 will return an incorrect result. This will show up as test 7 of
220 reduce.t failing.
221
222 =head1 SUGGESTED ADDITIONS
223
224 The following are additions that have been requested, but I have been reluctant
225 to add due to them being very simple to implement in perl
226
227   # One argument is true
228
229   sub any { $_ && return 1 for @_; 0 }
230
231   # All arguments are true
232
233   sub all { $_ || return 0 for @_; 1 }
234
235   # All arguments are false
236
237   sub none { $_ && return 0 for @_; 1 }
238
239   # One argument is false
240
241   sub notall { $_ || return 1 for @_; 0 }
242
243   # How many elements are true
244
245   sub true { scalar grep { $_ } @_ }
246
247   # How many elements are false
248
249   sub false { scalar grep { !$_ } @_ }
250
251 =head1 COPYRIGHT
252
253 Copyright (c) 1997-2004 Graham Barr <gbarr@pobox.com>. All rights reserved.
254 This program is free software; you can redistribute it and/or
255 modify it under the same terms as Perl itself.
256
257 =cut