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