File Coverage

blib/lib/LINQ/Collection.pm
Criterion Covered Total %
statement 356 359 99.1
branch 141 144 99.3
condition 19 21 90.4
subroutine 72 74 97.3
pod 47 47 100.0
total 635 645 98.7


line stmt bran cond sub pod time code
1 116     116   66640 use 5.006;
  116         456  
2 116     116   683 use strict;
  116         226  
  116         2493  
3 116     116   552 use warnings;
  116         227  
  116         6778  
4              
5              
6             our $AUTHORITY = 'cpan:TOBYINK';
7             our $VERSION = '0.003';
8              
9             use Role::Tiny;
10 116     116   716 use LINQ::Util::Internal ();
  116         304  
  116         723  
11 116     116   45735  
  116         279  
  116         576012  
12             requires qw( to_list );
13              
14             my $_coerce = sub {
15             my ( $thing ) = @_;
16            
17             require Scalar::Util;
18             if ( Scalar::Util::blessed( $thing ) and $thing->DOES( __PACKAGE__ ) ) {
19             return $thing;
20             }
21            
22             if ( ref( $thing ) eq 'ARRAY' ) {
23             require LINQ::Array;
24             return LINQ::Array::->new( $thing );
25             }
26            
27             LINQ::Util::Internal::throw(
28             "CallerError",
29             message => "Expected a LINQ collection; got '$thing'"
30             );
31             };
32              
33             my $self = shift;
34             my $map = LINQ::Util::Internal::assert_code( @_ );
35 84     84 1 293
36 84         233 my $iter = $self->to_iterator;
37             my $stopped;
38 84         228
39 84         164 require LINQ;
40             LINQ::LINQ(
41 84         481 sub {
42             # uncoverable branch true
43             return LINQ::END() if $stopped;
44             my @got = $iter->();
45 468 50   468   901 if ( @got ) {
46 468         805 local $_;
47 468 100       973 return scalar $map->( $_ = $got[0] );
48 384         565 }
49 384         1014 ++$stopped;
50             return LINQ::END();
51 84         186 }
52 84         260 );
53             } #/ sub select
54 84         461  
55             my $self = shift;
56             my $filter = LINQ::Util::Internal::assert_code( @_ );
57            
58 160     160 1 513 my $iter = $self->to_iterator;
59 160         445 my $stopped;
60            
61 160         431 require LINQ;
62 160         272 LINQ::LINQ(
63             sub {
64 160         740 GETVAL: {
65             return LINQ::END() if $stopped;
66             my @got = $iter->();
67             if ( @got ) {
68 424 100   424   600 local $_;
  1151         1909  
69 1149         1950 my $pass = $filter->( $_ = $got[0] );
70 1149 100       2251 return $got[0] if $pass;
71 1022         1378 redo GETVAL;
72 1022         2967 }
73 1009 100       11396 ++$stopped;
74 727         1260 return LINQ::END();
75             } #/ GETVAL:
76 127         311 }
77 127         367 );
78             } #/ sub where
79              
80 160         856 my $self = shift;
81             my $map = LINQ::Util::Internal::assert_code( @_ );
82            
83             my $outer = $self->to_iterator;
84 4     4 1 21 my $inner;
85 4         16 my $end;
86            
87 4         9 require LINQ;
88 4         8 LINQ::LINQ(
89             sub {
90             BODY: {
91 4         21 return LINQ::END() if $end;
92             if ( not $inner ) {
93             $inner = $outer->();
94             if ( defined $inner ) {
95 28 100   28   33 local $_;
  56         128  
96 52 100       98 $inner = $map->( $_ = $inner )->$_coerce->to_iterator;
97 28         60 }
98 28 100       47 else {
99 24         31 $end = 1;
100 24         50 redo BODY;
101             }
102             } #/ if ( not $inner )
103 4         12 my @got = $inner->();
104 4         9 if ( not @got ) {
105             undef $inner;
106             redo BODY;
107 48         99 }
108 48 100       96 return @got;
109 24         63 } #/ BODY:
110 24         41 }
111             );
112 24         61 } #/ sub select_many
113              
114             my $self = shift;
115 4         18 return $self->select( @_ )->min if @_;
116             require List::Util;
117             &List::Util::min( $self->to_list );
118             }
119 6     6 1 10  
120 6 100       17 my $self = shift;
121 4         22 return $self->select( @_ )->max if @_;
122 4         10 require List::Util;
123             &List::Util::max( $self->to_list );
124             }
125              
126 6     6 1 11 my $self = shift;
127 6 100       25 return $self->select( @_ )->sum if @_;
128 4         22 require List::Util;
129 4         10 &List::Util::sum( $self->to_list );
130             }
131              
132             my $self = shift;
133 12     12 1 20 $self->sum( @_ ) / $self->count();
134 12 100       38 }
135 8         41  
136 8         21 my $self = shift;
137             my $code = LINQ::Util::Internal::assert_code( shift );
138             my $wrapper = sub { $code->( $a, $b ) };
139             require List::Util;
140 4     4 1 8 &List::Util::reduce( $wrapper, @_, $self->to_list );
141 4         10 }
142              
143             my $_prepare_join = sub {
144             my $x = shift;
145 5     5 1 10 my $y = shift;
146 5         14
147 5     11   14 my $hint = ref( $_[0] ) ? -inner : shift( @_ );
  11         59  
148 5         26 my $x_keys = LINQ::Util::Internal::assert_code( shift );
149 5         15 my $y_keys = LINQ::Util::Internal::assert_code( shift );
150             my $joiner = LINQ::Util::Internal::assert_code( @_ );
151            
152             $hint =~ /\A-(inner|left|right|outer)\z/
153             or LINQ::Util::Internal::throw(
154             "CallerError",
155             message => "Expected a recognized join type; got '$hint'"
156             );
157            
158             my @x_mapped =
159             $x->select( sub { [ scalar( $x_keys->( $_[0] ) ), $_[0] ] } )->to_list;
160             my @y_mapped =
161             $y->select( sub { [ scalar( $y_keys->( $_[0] ) ), $_[0] ] } )->to_list;
162            
163             return ( \@x_mapped, \@y_mapped, $hint, $joiner );
164             };
165              
166             my ( $x_mapped, $y_mapped, $hint, $joiner ) = $_prepare_join->( @_ );
167            
168             my @joined;
169             my ( @found_x, @found_y );
170            
171             for my $Xi ( 0 .. $#$x_mapped ) {
172             my $X = $x_mapped->[$Xi];
173            
174             for my $Yi ( 0 .. $#$y_mapped ) {
175             my $Y = $y_mapped->[$Yi];
176 14     14 1 49
177             if ( $X->[0] eq $Y->[0] ) {
178 14         25 my $a = $X->[1];
179 14         25 my $b = $Y->[1];
180             $found_x[$Xi]++;
181 14         42 $found_y[$Yi]++;
182 68         762
183             push @joined, scalar $joiner->( $a, $b );
184 68         117 }
185 384         3810 } #/ for my $Yi ( 0 .. $#$y_mapped)
186             } #/ for my $Xi ( 0 .. $#$x_mapped)
187 384 100       936
188 68         89 if ( $hint eq -left or $hint eq -outer ) {
189 68         91 for my $Xi ( 0 .. $#$x_mapped ) {
190 68         93 next if $found_x[$Xi];
191 68         129 my $a = $x_mapped->[$Xi][1];
192             my $b = undef;
193 68         154 push @joined, scalar $joiner->( $a );
194             }
195             }
196            
197             if ( $hint eq -right or $hint eq -outer ) {
198 14 100 100     66 for my $Yi ( 0 .. $#$y_mapped ) {
199 7         25 next if $found_y[$Yi];
200 35 100       361 my $a = undef;
201 12         29 my $b = $y_mapped->[$Yi][1];
202 12         16 push @joined, scalar $joiner->( undef, $b );
203 12         27 }
204             }
205            
206             LINQ::Util::Internal::create_linq( \@joined );
207 14 100 100     117 } #/ sub join
208 6         16  
209 36 100       66 my ( $x_mapped, $y_mapped, $hint, $joiner ) = $_prepare_join->( @_ );
210 6         10
211 6         9 $hint =~ /\A-(left|inner)\z/ or LINQ::Util::Internal::throw(
212 6         16 "CallerError",
213             message => "Join type '$hint' not supported for group_join",
214             );
215            
216 14         274 my @joined;
217             my ( @found_x, @found_y );
218            
219             for my $Xi ( 0 .. $#$x_mapped ) {
220 9     9 1 36 my $X = $x_mapped->[$Xi];
221             my @group = map $_->[1], grep $X->[0] eq $_->[0], @$y_mapped;
222 9 100       61
223             if ( @group or $hint eq -left ) {
224             my $a = $X->[1];
225             my $b = LINQ::Util::Internal::create_linq( \@group );
226             push @joined, scalar $joiner->( $a, $b );
227 5         8 }
228 5         17 } #/ for my $Xi ( 0 .. $#$x_mapped)
229            
230 5         20 LINQ::Util::Internal::create_linq( \@joined );
231 23         168 } #/ sub group_join
232 23         135  
233             my $self = shift;
234 23 100 100     76 my ( $n ) = @_;
235 19         28 $self->take_while( sub { $n-- > 0 } );
236 19         58 }
237 19         43  
238             my $self = shift;
239             my $filter = LINQ::Util::Internal::assert_code( @_ );
240             my $stopped = 0;
241 5         41 my $iter = $self->to_iterator;
242            
243             require LINQ;
244             LINQ::LINQ(
245 13     13 1 50 sub {
246 13         28 # uncoverable branch true
247 13     66   58 return LINQ::END() if $stopped;
  66         214  
248             my @got = $iter->();
249             if ( !@got or !$filter->( $_ = $got[0] ) ) {
250             $stopped++;
251 21     21 1 61 return LINQ::END();
252 21         56 }
253 21         41 return $got[0];
254 21         53 }
255             );
256 21         108 } #/ sub take_while
257              
258             my $self = shift;
259             my ( $n ) = @_;
260 100 50   100   194 $self->skip_while( sub { $n-- > 0 } );
261 100         170 }
262 98 100 100     299  
263 19         51 my $self = shift;
264 19         74 my $filter = LINQ::Util::Internal::assert_code( @_ );
265             my $stopped = 0;
266 79         241 my $started = 0;
267             my $iter = $self->to_iterator;
268 21         131
269             require LINQ;
270             LINQ::LINQ(
271             sub {
272 8     8 1 24 SKIPPING: {
273 8         15 return LINQ::END() if $stopped;
274 8     24   33 my @got = $iter->();
  24         55  
275             if ( !@got ) {
276             $stopped++;
277             redo SKIPPING;
278 14     14 1 39 }
279 14         37 return $got[0] if $started;
280 14         24 if ( $filter->( $_ = $got[0] ) ) {
281 14         21 redo SKIPPING;
282 14         32 }
283             ++$started;
284 14         78 return $got[0];
285             } #/ SKIPPING:
286             }
287             );
288 76 100   76   96 } #/ sub skip_while
  118         209  
289 104         179  
290 104 100       188 my @collections = map $_->to_iterator, @_;
291 14         20 my $idx = 0;
292 14         26
293             require LINQ;
294 90 100       199 LINQ::LINQ(
295 40 100       83 sub {
296 28         70 FIND_NEXT: {
297             return LINQ::END() if not @collections;
298 12         44
299 12         58 my @got = $collections[0]->();
300             if ( not @got ) {
301             shift @collections;
302 14         59 redo FIND_NEXT;
303             }
304            
305             return $got[0];
306 12     12 1 38 } #/ FIND_NEXT:
307 12         24 }
308             );
309 12         47 } #/ sub concat
310              
311             my $self = shift;
312             my ( $hint, $keygen ) = ( -numeric, undef );
313 100 100   100   132 if ( @_ ) {
  121         227  
314             $hint = ref( $_[0] ) ? -numeric : shift( @_ );
315 111         191 $keygen = @_ ? LINQ::Util::Internal::assert_code( @_ ) : undef;
316 111 100       241 }
317 21         57
318 21         76 if ( not $keygen ) {
319             if ( $hint eq -string ) {
320             return LINQ::Util::Internal::create_linq(
321 90         205 [ sort { $a cmp $b } $self->to_list ] );
322             }
323             elsif ( $hint eq -numeric ) {
324 12         47 return LINQ::Util::Internal::create_linq(
325             [ sort { $a <=> $b } $self->to_list ] );
326             }
327             } #/ if ( not $keygen )
328 49     49 1 25510
329 49         128 if ( $hint eq -string ) {
330 49 100       136 return LINQ::Util::Internal::create_linq(
331 47 100       138 [
332 47 100       196 map $_->[1],
333             sort { $a->[0] cmp $b->[0] }
334             map [ $keygen->( $_ ), $_ ],
335 49 100       165 $self->to_list
336 12 100       40 ]
    100          
337             );
338 2         8 } #/ if ( $hint eq -string )
  10         26  
339            
340             elsif ( $hint eq -numeric ) {
341             return LINQ::Util::Internal::create_linq(
342 8         25 [
  40         101  
343             map $_->[1],
344             sort { $a->[0] <=> $b->[0] }
345             map [ $keygen->( $_ ), $_ ],
346 39 100       121 $self->to_list
    100          
347             ]
348             );
349             } #/ elsif ( $hint eq -numeric)
350 23         74
  173         710  
351             LINQ::Util::Internal::throw(
352             "CallerError",
353             message => "Expected '-numeric' or '-string'; got '$hint'"
354             );
355             } #/ sub order_by
356              
357             LINQ::Util::Internal::throw( "Unimplemented", method => "then_by" );
358             }
359              
360             my $self = shift;
361 14         46 $self->order_by( @_ )->reverse;
  86         491  
362             }
363              
364             LINQ::Util::Internal::throw( "Unimplemented", method => "then_by_descending" );
365             }
366              
367             my $self = shift;
368             LINQ::Util::Internal::create_linq(
369 2         10 [ reverse( $self->to_list ) ],
370             );
371             }
372              
373             my $self = shift;
374             my $keygen = LINQ::Util::Internal::assert_code( @_ );
375 2     2 1 7
376             my @keys;
377             my %values;
378            
379 6     6 1 26 for ( $self->to_list ) {
380 6         14 my $key = $keygen->( $_ );
381             unless ( $values{$key} ) {
382             push @keys, $key;
383             $values{$key} = [];
384 2     2 1 7 }
385             push @{ $values{$key} }, $_;
386             }
387            
388 8     8 1 43 require LINQ::Grouping;
389 8         23 LINQ::Util::Internal::create_linq(
390             [
391             map 'LINQ::Grouping'->new(
392             key => $_,
393             values => LINQ::Util::Internal::create_linq( $values{$_} ),
394             ),
395 2     2 1 15 @keys
396 2         6 ]
397             );
398 2         4 } #/ sub group_by
399              
400             my $self = shift;
401 2         6 my $compare =
402 20         34 @_ ? LINQ::Util::Internal::assert_code( @_ ) : sub { $_[0] == $_[1] };
403 20 100       66
404 6         13 my @already;
405 6         9 $self->where(
406             sub {
407 20         30 my $maybe = $_[0];
  20         35  
408             for my $got ( @already ) {
409             return !!0 if $compare->( $maybe, $got );
410 2         856 }
411             push @already, $maybe;
412             return !!1;
413             }
414             );
415 2         14 } #/ sub distinct
416              
417             my $self = shift;
418             my ( $other, @compare ) = @_;
419             $self->concat( $other )->distinct( @compare );
420             }
421              
422             my $self = shift;
423 8     8 1 14 my $other = shift;
424             my @compare =
425 8 100   36   66 @_ ? LINQ::Util::Internal::assert_code( @_ ) : sub { $_[0] == $_[1] };
  36         99  
426             $self->where( sub { $other->contains( $_, @compare ) } );
427 8         14 }
428              
429             my $self = shift;
430 46     46   69 my $other = shift;
431 46         85 my @compare =
432 86 100       284 @_ ? LINQ::Util::Internal::assert_code( @_ ) : sub { $_[0] == $_[1] };
433             $self->where( sub { not $other->contains( $_, @compare ) } );
434 34         194 }
435 34         70  
436             my $self = shift;
437 8         32 my ( $other, @compare ) = @_;
438            
439             my $compare;
440             if ( @compare ) {
441 4     4 1 18 $compare = LINQ::Util::Internal::assert_code( @compare );
442 4         8 }
443 4         11
444             my $iter1 = $self->to_iterator;
445             my $iter2 = $other->to_iterator;
446            
447 4     4 1 19 while ( 1 ) {
448 4         8 my @got1 = $iter1->();
449             my @got2 = $iter2->();
450 4 100   12   35
  12         29  
451 4     10   15 if ( not @got1 ) {
  10         25  
452             if ( @got2 ) {
453             return !!0;
454             }
455 4     4 1 20 else {
456 4         4 return !!1;
457             }
458 4 100   12   20 }
  12         25  
459 4     10   24 elsif ( not @got2 ) {
  10         22  
460             return !!0;
461             }
462            
463 18     18 1 59 if ( $compare ) {
464 18         32 return !!0 unless $compare->( $got1[0], $got2[0] );
465             }
466 18         25 else {
467 18 100       44 return !!0 unless $got1[0] == $got2[0];
468 12         32 }
469             } #/ while ( 1 )
470             } #/ sub sequence_equal
471 18         41  
472 18         36 my $_with_default = sub {
473             my $self = shift;
474 18         29 my $method = shift;
475 114         305 my @args = @_;
476 114         175 my $default = pop( @args );
477            
478 114 100       253 my $return;
    100          
479 10 100       27 eval { $return = $self->$method( @args ); 1 } or do {
480 4         30 my $e = $@; # catch
481            
482             # Rethrow any non-blessed errors.
483 6         48 require Scalar::Util;
484             die( $e ) unless Scalar::Util::blessed( $e );
485            
486             # Rethrow any errors of the wrong class.
487 2         15 die( $e )
488             unless $e->isa( 'LINQ::Exception::NotFound' )
489             || $e->isa( 'LINQ::Exception::MultipleFound' );
490 102 100       153
491 60 100       113 # Rethrow any errors which resulted from the wrong source.
492             die( $e ) unless $e->collection == $self;
493            
494 42 100       90 return $default;
495             };
496            
497             return $return;
498             };
499              
500             my $self = shift;
501             my $found = @_ ? $self->where( @_ ) : $self;
502             return $found->element_at( 0 ) if $found->count > 0;
503             LINQ::Util::Internal::throw( 'NotFound', collection => $self );
504             }
505              
506             shift->$_with_default( first => @_ );
507             }
508              
509             my $self = shift;
510             my $found = @_ ? $self->where( @_ ) : $self;
511             return $found->element_at( -1 ) if $found->count > 0;
512             LINQ::Util::Internal::throw( 'NotFound', collection => $self );
513             }
514              
515             shift->$_with_default( last => @_ );
516             }
517              
518             my $self = shift;
519             my $found = @_ ? $self->where( @_ ) : $self;
520             return $found->element_at( 0 ) if $found->count == 1;
521             $found->count == 0
522             ? LINQ::Util::Internal::throw( 'NotFound', collection => $self )
523             : LINQ::Util::Internal::throw( 'MultipleFound', collection => $self,
524             found => $found );
525             }
526              
527             shift->$_with_default( single => @_ );
528 13     13 1 23 }
529 13 100       47  
530 13 100       44 my $self = shift;
531 4         20 my ( $i ) = @_;
532            
533             my @list = $self->to_list;
534            
535 6     6 1 151 if ( $i > $#list ) {
536             LINQ::Util::Internal::throw( 'NotFound', collection => $self );
537             }
538            
539 13     13 1 35 if ( $i < 0 - @list ) {
540 13 100       52 LINQ::Util::Internal::throw( 'NotFound', collection => $self );
541 13 100       43 }
542 4         22
543             $list[$i];
544             } #/ sub element_at
545              
546 6     6 1 162 shift->$_with_default( element_at => @_ );
547             }
548              
549             my $self = shift;
550 32     32 1 356 my $iter = @_ ? $self->where( @_ )->to_iterator : $self->to_iterator;
551 32 100       118 my @got = $iter->();
552 32 100       87 !!scalar @got;
553 8 100       24 }
554              
555             my $self = shift;
556             my $check = LINQ::Util::Internal::assert_code( @_ );
557             my $iter = $self->where( sub { not $check->( $_ ) } )->to_iterator;
558             my @got = $iter->();
559             !scalar @got;
560 8     8 1 246 }
561              
562             my $self = shift;
563             my ( $x, @args ) = @_;
564 60     60 1 112
565 60         108 if ( @args ) {
566             splice( @args, 1, 0, $x );
567 60         172 return $self->any( LINQ::Util::Internal::assert_code( @args ) );
568             }
569 60 100       204
570 2         7 my $iter = $self->to_iterator;
571             while ( 1 ) {
572             my @got = $iter->() or return !!0;
573 58 100       176 return !!1 if $got[0] == $x;
574 2         9 }
575             } #/ sub contains
576              
577 56         433 my $self = shift;
578             return $self->where( @_ )->count if @_;
579             my @list = $self->to_list;
580             return scalar( @list );
581 24     24 1 57 }
582              
583             my $self = shift;
584             [ $self->to_list ];
585 32     32 1 55 }
586 32 100       120  
587 32         120 my $self = shift;
588 32         355 my ( $keygen ) = LINQ::Util::Internal::assert_code( @_ );
589             +{ map +( $keygen->( $_ ), $_ ), $self->to_list };
590             }
591              
592 8     8 1 32 my $self = shift;
593 8         24 $self->to_dictionary( @_ );
594 8     15   32 }
  15         72  
595 8         41  
596 8         126 my $self = shift;
597             my @list = $self->to_list;
598             sub { @list ? shift( @list ) : () };
599             }
600 31     31 1 53  
601 31         61 my $self = shift;
602             my ( $type ) = @_;
603 31 100       70
604 24         53 my $cast = $self->of_type( @_ );
605 24         74 return $cast if $self->count == $cast->count;
606            
607             LINQ::Util::Internal::throw( "Cast", collection => $self, type => $type );
608 7         31 }
609 7         13  
610 187 100       293 my $self = shift;
611 184 100       368 my ( $type ) = @_;
612            
613             require Scalar::Util;
614            
615             unless ( Scalar::Util::blessed( $type ) and $type->can( 'check' ) ) {
616 99     99 1 345 LINQ::Util::Internal::throw(
617 99 100       295 "CallerError",
618 98         270 message => "Expected type constraint; got '$type'",
619 92         431 );
620             }
621            
622             if ( $type->isa( 'Type::Tiny' ) ) {
623 61     61 1 24560 my $check = $type->compiled_check;
624 61         172
625             if ( $type->has_coercion ) {
626             my $coercion = $type->coercion->compiled_coercion;
627             return $self->select( $coercion )->where( $check );
628 4     4 1 8 }
629 4         26
630 4         16 return $self->where( $check );
631             } #/ if ( $type->isa( 'Type::Tiny'...))
632            
633             if ( $type->can( 'has_coercion' ) and $type->has_coercion ) {
634 2     2 1 4 return $self
635 2         5 ->select( sub { $type->coerce( $_ ) } )
636             ->where( sub { $type->check( $_ ) } );
637             }
638            
639 195     195 1 288 return $self->where( sub { $type->check( $_ ) } );
640 195         499 } #/ sub of_type
641 195 100   1072   703  
  1072         2504  
642             my $self = shift;
643             my $other = shift;
644             my $map = LINQ::Util::Internal::assert_code( @_ );
645 7     7 1 47001
646 7         17 my $iter1 = $self->to_iterator;
647             my $iter2 = $other->to_iterator;
648 7         20 my @results;
649 7 100       23
650             require LINQ;
651 4         15 LINQ::LINQ(
652             sub {
653             my @r1 = $iter1->();
654             my @r2 = $iter2->();
655 23     23 1 6071 return LINQ::END() unless @r1 && @r2;
656 23         45 $map->( $r1[0], $r2[0] );
657             }
658 23         120 );
659             } #/ sub zip
660 23 100 100     211  
661 8         45 my $self = shift;
662             my $item = shift;
663            
664             if ( $self->count == 0 ) {
665             return LINQ::Util::Internal::create_linq( [$item] );
666             }
667 15 100       209
668 11         136 return $self;
669             } #/ sub default_if_empty
670 11 100       199  
671 7         89 my $self = shift;
672 7         6182 my $code = LINQ::Util::Internal::assert_code( @_ );
673            
674             my $ok = eval {
675 4         196 local $LINQ::IN_LOOP = 1;
676             $self->where( sub { $code->( $_ ); 0 } )->to_list;
677             1;
678 4 50 33     19 };
679             if ( not $ok ) {
680 0     0   0 my $e = $@;
681 0     0   0 require Scalar::Util;
  0         0  
682             die( $e ) unless Scalar::Util::blessed( $e );
683             die( $e ) unless $e->isa( 'LINQ::LAST' );
684 4     36   20 }
  36         71  
685             return;
686             } #/ sub foreach
687              
688 4     4 1 25 1;
689 4         7  
690 4         11  
691             =pod
692 4         10  
693 4         11 =encoding utf-8
694 4         6  
695             =head1 NAME
696 4         19  
697             LINQ - the interface which all LINQ collections share
698              
699 44     44   71 =head1 SYNOPSIS
700 44         76  
701 44 100 100     136 use feature 'say';
702 40         85 use LINQ 'LINQ';
703            
704 4         19 my $double_even_numbers =
705             LINQ( [1..100] )
706             ->where( sub { $_ % 2 == 0 } )
707             ->select( sub { $_ * 2 } );
708 4     4 1 23
709 4         7 if ( not $double_even_numbers->DOES( 'LINQ::Collection' ) ) {
710             die "What? But you said they all do it!";
711 4 100       9 }
712 2         7
713             for my $n ( $double_even_numbers->to_list ) {
714             say $n;
715 2         10 }
716              
717             =head1 DESCRIPTION
718              
719 9     9 1 6159 Objects returned by the C<< LINQ() >>, C<< LINQ::Repeat() >>, and
720 9         27 C<< LINQ::Range() >> functions all provide the LINQ::Collection interface.
721             Many of the methods in this interface also return new objects which provide
722 9         17 this interface.
723 9         15  
724 9     234   36 =head1 METHODS
  234         475  
  227         582  
725 2         16  
726             Many methods take a parameter "CALLABLE". This means they can accept a
727 9 100       139 coderef, an object overloading C<< &{} >>, or an arrayref where the first
728 7         12 item is one of the previous two things and the remainder are treated as
729 7         28 arguments to curry to the first argument. A quoted regexp C<< qr/.../ >> can
730 7 100       43 also be used as a callable.
731 5 100       54  
732             If using an arrayref, it is generally permissable to flatten it into a
733 5         15 list, unless otherwise noted. An example of this can be seen in the
734             documentation for C<select>.
735              
736             =over
737              
738             =item C<< select( CALLABLE ) >>
739              
740             LINQ's version of C<map>, except that the code given is always called in
741             scalar context, being expected to return exactly one result.
742              
743             Returns a LINQ::Collection of the results.
744              
745             my $people = LINQ( [
746             { name => "Alice", age => 32 },
747             { name => "Bob", age => 31 },
748             { name => "Carol", age => 34 },
749             ] );
750            
751             my $names = $people->select( sub {
752             return $_->{name};
753             } );
754            
755             for my $name ( $names->to_list ) {
756             print "$name\n";
757             }
758              
759             Another way of doing the same thing, using currying:
760              
761             my $people = LINQ( [
762             { name => "Alice", age => 32 },
763             { name => "Bob", age => 31 },
764             { name => "Carol", age => 34 },
765             ] );
766            
767             my $BY_HASH_KEY = sub {
768             my ($key) = @_;
769             return $_->{$key};
770             };
771            
772             my $names = $people->select( $BY_HASH_KEY, 'name' );
773            
774             for my $name ( $names->to_list ) {
775             print "$name\n";
776             }
777              
778             =item C<< select_many( CALLABLE ) >>
779              
780             If you wanted C<select> to be able to return a list like C<map> does, then
781             C<select_many> is what you want. However, rather than returning a Perl list,
782             your callable should return a LINQ::Collection or an arrayref.
783              
784             =item C<< where( CALLABLE ) >>
785              
786             LINQ's version of C<grep>. Returns a LINQ::Collection of the filtered results.
787              
788             my $people = LINQ( [
789             { name => "Alice", age => 32 },
790             { name => "Bob", age => 31 },
791             { name => "Carol", age => 34 },
792             ] );
793            
794             my $young_people = $people->where( sub {
795             return $_->{age} < 33;
796             } );
797              
798             =item C<< min( CALLABLE? ) >>
799              
800             Returns the numerically lowest value in the collection.
801              
802             my $lowest = LINQ( [ 5, 1, 2, 3 ] )->min; # ==> 1
803              
804             If a callable is provided, then C<select> will be called and the minimum of the
805             result will be returned.
806              
807             my $people = LINQ( [
808             { name => "Alice", age => 32 },
809             { name => "Bob", age => 31 },
810             { name => "Carol", age => 34 },
811             ] );
812            
813             my $lowest_age = $people->min( sub { $_->{age} } ); # ==> 31
814              
815             If you need more flexible comparison (e.g. non-numeric comparison), use
816             C<order_by> followed by C<first>.
817              
818             =item C<< max( CALLABLE? ) >>
819              
820             Like C<min>, but returns the numerically highest value.
821              
822             =item C<< sum( CALLABLE? ) >>
823              
824             Like C<min>, but returns the sum of all values in the collection.
825              
826             =item C<< average( CALLABLE? ) >>
827              
828             Takes C<sum>, and divides by the count of items in the collection.
829              
830             my $people = LINQ( [
831             { name => "Alice", age => 32 },
832             { name => "Bob", age => 31 },
833             { name => "Carol", age => 34 },
834             ] );
835            
836             my $average_age = $people->average( sub {
837             return $_->{age};
838             } ); # ==> 32.33333
839              
840             =item C<< aggregate( CALLABLE, INITIAL? ) >>
841              
842             LINQ's version of C<reduce> (from L<List::Util>). We pass C<< $a >> and
843             C<< $b >> as the last arguments to CALLABLE, rather than using the package
844             variables like List::Util does.
845              
846             The CALLABLE must not be a flattened list, but may still be an arrayref.
847             INITIAL is an initial value.
848              
849             my $people = LINQ( [
850             { name => "Alice", age => 32 },
851             { name => "Bob", age => 31 },
852             { name => "Carol", age => 34 },
853             ] );
854            
855             my dotted_names = $people
856             ->select( sub { $_->{name} } )
857             ->aggregate( sub {
858             my ( $a, $b ) = @_;
859             return "$a.$b";
860             } );
861            
862             print "$dotted_names\n"; # ==> Alice.Bob.Carol
863              
864             =item C<< join( Y, HINT?, X_KEYS, Y_KEYS, JOINER ) >>
865              
866             This is akin to an SQL join.
867              
868             my $people = LINQ( [
869             { name => "Alice", dept => 'Marketing' },
870             { name => "Bob", dept => 'IT' },
871             { name => "Carol", dept => 'IT' },
872             ] );
873            
874             my $departments = LINQ( [
875             { dept_name => 'Accounts', cost_code => 1 },
876             { dept_name => 'IT', cost_code => 7 },
877             { dept_name => 'Marketing', cost_code => 8 },
878             ] );
879            
880             my $BY_HASH_KEY = sub {
881             my ($key) = @_;
882             return $_->{$key};
883             };
884            
885             my $joined = $people->join(
886             $departments,
887             -inner, # inner join
888             [ $BY_HASH_KEY, 'dept' ], # select from $people
889             [ $BY_HASH_KEY, 'dept_name' ], # select from $departments
890             sub {
891             my ( $person, $dept ) = @_;
892             return {
893             name => $person->{name},
894             dept => $person->{dept},
895             expense_code => $dept->{cost_code},
896             };
897             },
898             );
899              
900             Hints C<< -inner >>, C<< -left >>, C<< -right >>, and C<< -outer >> are
901             supported, analagous to the joins with the same names in SQL.
902              
903             X_KEYS and Y_KEYS are non-list callables which return the values to join the
904             two collections by.
905              
906             JOINER is a callable (which may be a flattened list) which is passed items
907             from each of the two collections and should return a new item. In the case
908             of left/right/outer joins, one of those items may be undef.
909              
910             =item C<< group_join( Y, HINT?, X_KEYS, Y_KEYS, JOINER ) >>
911              
912             Similar to C<group> except that rather than JOINER being called for every
913             X/Y combination, all the Ys for a particular X are put in a collection, and
914             the JOINER is called for each X and passed the collection of Ys.
915              
916             The only hints supported are C<< -inner >> and C<< -left >>.
917              
918             This is best explained with a full example:
919              
920             my $departments = LINQ( [
921             { dept_name => 'Accounts', cost_code => 1 },
922             { dept_name => 'IT', cost_code => 7 },
923             { dept_name => 'Marketing', cost_code => 8 },
924             ] );
925            
926             my $people = LINQ( [
927             { name => "Alice", dept => 'Marketing' },
928             { name => "Bob", dept => 'IT' },
929             { name => "Carol", dept => 'IT' },
930             ] );
931            
932             my $BY_HASH_KEY = sub {
933             my ($key) = @_;
934             return $_->{$key};
935             };
936            
937             my $joined = $departments->group_join(
938             $people,
939             -left, # left join
940             [ $BY_HASH_KEY, 'dept_name' ], # select from $departments
941             [ $BY_HASH_KEY, 'dept' ], # select from $people
942             sub {
943             my ( $dept, $people ) = @_; # $people is a LINQ::Collection
944             my $names = $people->select( $BY_HASH_KEY, 'name' )->to_array;
945             return {
946             dept => $dept->{dept_name},
947             cost_code => $dept->{cost_code},
948             people => $names,
949             };
950             },
951             );
952            
953             # [
954             # {
955             # 'cost_code' => 1,
956             # 'dept' => 'Accounts',
957             # 'people' => []
958             # },
959             # {
960             # 'cost_code' => 7,
961             # 'dept' => 'IT',
962             # 'people' => [
963             # 'Bob',
964             # 'Carol'
965             # ]
966             # },
967             # {
968             # 'cost_code' => 8,
969             # 'dept' => 'Marketing',
970             # 'people' => [
971             # 'Alice'
972             # ]
973             # }
974              
975             =item C<< take( N ) >>
976              
977             Takes just the first N items from a collection, returning a new collection.
978              
979             =item C<< take_while( CALLABLE ) >>
980              
981             Takes items from the collection, stopping at the first item where CALLABLE
982             returns false.
983              
984             If CALLABLE dies, there are some issues on older versions of Perl with the
985             error message getting lost.
986              
987             =item C<< skip( N ) >>
988              
989             Skips the first N items from a collection, and returns the rest as a new
990             collection.
991              
992             =item C<< skip_while( CALLABLE ) >>
993              
994             Skips the first items from a collection while CALLABLE returns true, and
995             returns the rest as a new collection.
996              
997             =item C<< concat( COLLECTION ) >>
998              
999             Returns a new collection by concatenating this collection with another
1000             collection.
1001              
1002             my $deck_of_cards = $red_cards->concat( $black_cards );
1003              
1004             =item C<< order_by( HINT?, CALLABLE? ) >>
1005              
1006             HINT may be C<< -numeric >> (the default) or C<< -string >>.
1007              
1008             If CALLABLE is given, it should return a number or string to sort by.
1009              
1010             my $sorted = $people->order_by(
1011             -string,
1012             [ $BY_HASH_KEY, 'name' ] # CALLABLE as an arrayref
1013             );
1014              
1015             =item C<< then_by( HINT?, CALLABLE ) >>
1016              
1017             Not implemented.
1018              
1019             =item C<< order_by_descending( HINT?, CALLABLE ) >>
1020              
1021             Like C<order_by> but uses reverse order.
1022              
1023             =item C<< then_by_descending( HINT?, CALLABLE ) >>
1024              
1025             Not implemented.
1026              
1027             =item C<< reverse >>
1028              
1029             Reverses the order of the collection.
1030              
1031             =item C<< group_by( CALLABLE ) >>
1032              
1033             Groups the items by the key returned by CALLABLE.
1034              
1035             The collection of groups is a LINQ::Collection and each grouping is a
1036             LINQ::Grouping. LINQ::Grouping provides two accessors: C<key> and C<values>,
1037             with C<values> returning a LINQ::Collection of items.
1038              
1039             my $people = LINQ( [
1040             { name => "Alice", dept => 'Marketing' },
1041             { name => "Bob", dept => 'IT' },
1042             { name => "Carol", dept => 'IT' },
1043             ] );
1044            
1045             my $groups = $people->group_by( sub { $_->{dept} } );
1046            
1047             for my $group ( $groups->to_list ) {
1048             print "Dept: ", $group->key, "\n";
1049            
1050             for my $person ( $group->values->to_list ) {
1051             print " - ", $person->{name};
1052             }
1053             }
1054              
1055             =item C<< distinct( CALLABLE? ) >>
1056              
1057             Returns a new collection without any duplicates which were in the original.
1058              
1059             If CALLABLE is provided, this will be used to determine when two items are
1060             considered identical/equivalent. Otherwise, numeric equality is used.
1061              
1062             =item C<< union( COLLECTION, CALLABLE? ) >>
1063              
1064             Returns a new collection formed from the union of both collections.
1065              
1066             my $first = LINQ( [ 1, 2, 3, 4 ] );
1067             my $second = LINQ( [ 3, 4, 5, 6 ] );
1068            
1069             $first->union( $second )->to_array; # ==> [ 1, 2, 3, 4, 5, 6 ]
1070              
1071             If CALLABLE is provided, this will be used to determine when two items are
1072             considered identical/equivalent. Otherwise, numeric equality is used.
1073              
1074             =item C<< intersect( COLLECTION, CALLABLE? ) >>
1075              
1076             Returns a new collection formed from the union of both collections.
1077              
1078             my $first = LINQ( [ 1, 2, 3, 4 ] );
1079             my $second = LINQ( [ 3, 4, 5, 6 ] );
1080            
1081             $first->intersect( $second )->to_array; # ==> [ 3, 4 ]
1082              
1083             If CALLABLE is provided, this will be used to determine when two items are
1084             considered identical/equivalent. Otherwise, numeric equality is used.
1085              
1086             =item C<< except( COLLECTION, CALLABLE? ) >>
1087              
1088             Returns a new collection formed from the asymmetric difference of both
1089             collections.
1090              
1091             my $first = LINQ( [ 1, 2, 3, 4 ] );
1092             my $second = LINQ( [ 3, 4, 5, 6 ] );
1093            
1094             $first->except( $second )->to_array; # ==> [ 1, 2 ]
1095              
1096             If CALLABLE is provided, this will be used to determine when two items are
1097             considered identical/equivalent. Otherwise, numeric equality is used.
1098              
1099             =item C<< sequence_equal( COLLECTION, CALLABLE? ) >>
1100              
1101             Returns true if and only if each item in the first collection is
1102             identical/equivalent to its corresponding item in the second collection,
1103             considered in order, according to CALLABLE.
1104              
1105             If CALLABLE isn't given, then numeric equality is used.
1106              
1107             =item C<< first( CALLABLE? ) >>
1108              
1109             Returns the first item in a collection.
1110              
1111             If CALLABLE is provided, returns the first item in the collection where
1112             CALLABLE returns true.
1113              
1114             If there is no item to return, does not return undef, but throws a
1115             LINQ::Exception::NotFound exception.
1116              
1117             =item C<< first_or_default( CALLABLE?, DEFAULT ) >>
1118              
1119             Like C<first>, but instead of throwing an exception, will return the DEFAULT.
1120              
1121             =item C<< last( CALLABLE? ) >>
1122              
1123             Returns the last item in a collection.
1124              
1125             If CALLABLE is provided, returns the last item in the collection where
1126             CALLABLE returns true.
1127              
1128             If there is no item to return, does not return undef, but throws a
1129             LINQ::Exception::NotFound exception.
1130              
1131             =item C<< last_or_default( CALLABLE?, DEFAULT ) >>
1132              
1133             Like C<last>, but instead of throwing an exception, will return the DEFAULT.
1134              
1135             =item C<< single( CALLABLE? ) >>
1136              
1137             Returns the only item in a collection.
1138              
1139             If CALLABLE is provided, returns the only item in the collection where
1140             CALLABLE returns true.
1141              
1142             If there is no item to return, does not return undef, but throws a
1143             LINQ::Exception::NotFound exception.
1144              
1145             If there are multiple items in the collection, or multiple items where
1146             CALLABLE returns true, throws a LINQ::Exception::MultipleFound exception.
1147              
1148             =item C<< single_or_default( CALLABLE?, DEFAULT ) >>
1149              
1150             Like C<single> but rather than throwing an exception, will return DEFAULT.
1151              
1152             =item C<< element_at( N ) >>
1153              
1154             Returns element N within the collection. N may be negative to count from the
1155             end of the collection. Collections are indexed from zero.
1156              
1157             If N exceeds the length of the collection, throws a LINQ::Exception::NotFound
1158             exception.
1159              
1160             =item C<< element_at_or_default( N, DEFAULT ) >>
1161              
1162             Like C<element_at> but rather than throwing an exception, will return DEFAULT.
1163              
1164             =item C<< any( CALLABLE? ) >>
1165              
1166             Returns true if CALLABLE returns true for any item in the collection.
1167              
1168             =item C<< all( CALLABLE? ) >>
1169              
1170             Returns true if CALLABLE returns true for every item in the collection.
1171              
1172             =item C<< contains( ITEM, CALLABLE? ) >>
1173              
1174             Returns true if the collection contains ITEM. By default, this is checked
1175             using numeric equality.
1176              
1177             If CALLABLE is given, this is passed two items and should return true
1178             if they should be considered identical/equivalent.
1179              
1180             my $SAME_NAME = sub {
1181             $_[0]{name} eq $_[1]{name};
1182             };
1183            
1184             if ( $people->contains( { name => "Bob" }, $SAME_NAME ) ) {
1185             print "The collection includes Bob.\n";
1186             }
1187              
1188             =item C<< count >>
1189              
1190             Returns the size of the collection. (Number of items.)
1191              
1192             =item C<< to_list >>
1193              
1194             Returns the collection as a list.
1195              
1196             =item C<< to_array >>
1197              
1198             Returns an arrayref for the collection. This may be a tied arrayref and you
1199             should not assume it will be writable.
1200              
1201             =item C<< to_dictionary( CALLABLE ) >>
1202              
1203             The CALLABLE will be called for each item in the collection and is expected to
1204             return a string key.
1205              
1206             The method will return a hashref mapping the keys to each item in the
1207             collection.
1208              
1209             =item C<< to_lookup( CALLABLE ) >>
1210              
1211             Alias for C<to_dictionary>.
1212              
1213             =item C<< to_iterator >>
1214              
1215             Returns a coderef which can be used to iterate through the collection.
1216              
1217             my $people = LINQ( [
1218             { name => "Alice", dept => 'Marketing' },
1219             { name => "Bob", dept => 'IT' },
1220             { name => "Carol", dept => 'IT' },
1221             ] );
1222            
1223             my $next_person = $people->to_iterator;
1224            
1225             while ( my $person = $next_person->() ) {
1226             print $person->{name}, "\n";
1227             }
1228              
1229             =item C<< cast( TYPE ) >>
1230              
1231             Given a type constraint (see L<Type::Tiny>) will attempt to coerce every item
1232             in the collection to the type, and will return the collection of coerced
1233             values. If any item cannot be coerced, throws a LINQ::Exception::Cast
1234             exception.
1235              
1236             =item C<< of_type( TYPE ) >>
1237              
1238             Given a type constraint (see L<Type::Tiny>) will attempt to coerce every item
1239             in the collection to the type, and will return the collection of coerced
1240             values. Any items which cannot be coerced will be skipped.
1241              
1242             =item C<< zip( COLLECTION, CALLABLE ) >>
1243              
1244             Will loop through both collections in parallel and pass one item from each
1245             collection to CALLABLE as arguments.
1246              
1247             If the two collections are of different sizes, will stop after exhausing the
1248             shorter collection.
1249              
1250             =item C<< default_if_empty( ITEM ) >>
1251              
1252             If this collection contains one or more items, returns itself.
1253              
1254             If the collection is empty, returns a new collection containing just a single
1255             item, given as a parameter.
1256              
1257             my $collection = $people->default_if_empty( "Bob" );
1258            
1259             # Equivalent to:
1260             my $collection = $people->count ? $people : LINQ( [ "Bob" ] );
1261              
1262             =item C<< foreach( CALLABLE ) >>
1263              
1264             This calls CALLABLE on each item in the collection. The following are roughly
1265             equivalent:
1266              
1267             for ( $collection->to_list ) {
1268             say $_;
1269             }
1270            
1271             $collection->foreach( sub {
1272             say $_;
1273             } );
1274              
1275             The advantage of the latter is that it avoids calling C<to_list>, which would
1276             obviously fail on infinite collections.
1277              
1278             You can break out of the loop using C<< LINQ::LAST >>.
1279              
1280             my $counter = 0;
1281             $collection->foreach( sub {
1282             say $_;
1283             LINQ::LAST if ++$counter >= 10;
1284             } );
1285              
1286             Microsoft's official LINQ API doesn't include a C<ForEach> method, but this
1287             method is provided by the MoreLINQ extension.
1288              
1289             =back
1290              
1291             =head1 WORKING WITH INFINITE COLLECTIONS
1292              
1293             Because LINQ collections can be instantiated from an iterator, they may
1294             contain infinite items.
1295              
1296             Certain methods aggregate the entire collection, so can go into an infinite
1297             loop. This includes: C<aggregate>, C<min>, C<max>, C<sum>, C<average>, and
1298             C<count>.
1299              
1300             Other methods which will go into an infinite loop on infinite collections:
1301             C<join>, C<group_join>, C<group_by>, C<order_by>, C<order_by_descending>,
1302             C<reverse>, C<to_lookup>, C<to_dictionary>, and C<to_list>.
1303              
1304             The C<to_array> method in general I<will> succeed on infinite collections
1305             as it can return a reference to a tied array. However, trying to dereference
1306             the entire array to a list will fail.
1307              
1308             =head1 BUGS
1309              
1310             Please report any bugs to
1311             L<http://rt.cpan.org/Dist/Display.html?Queue=LINQ>.
1312              
1313             =head1 SEE ALSO
1314              
1315             L<LINQ>, L<LINQ::Grouping>.
1316              
1317             L<https://en.wikipedia.org/wiki/Language_Integrated_Query>
1318              
1319             =head1 AUTHOR
1320              
1321             Toby Inkster E<lt>tobyink@cpan.orgE<gt>.
1322              
1323             =head1 COPYRIGHT AND LICENCE
1324              
1325             This software is copyright (c) 2014, 2021 by Toby Inkster.
1326              
1327             This is free software; you can redistribute it and/or modify it under
1328             the same terms as the Perl 5 programming language system itself.
1329              
1330             =head1 DISCLAIMER OF WARRANTIES
1331              
1332             THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
1333             WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
1334             MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.