File Coverage

blib/lib/LINQ/Iterator.pm
Criterion Covered Total %
statement 89 89 100.0
branch 28 28 100.0
condition 13 17 88.2
subroutine 20 20 100.0
pod 5 5 100.0
total 155 159 98.7


line stmt bran cond sub pod time code
1 100     100   3428 use 5.006;
  100         346  
2 100     100   526 use strict;
  100         175  
  100         2290  
3 100     100   530 use warnings;
  100         218  
  100         65380  
4              
5             if ( $] < 5.010000 ) {
6             require UNIVERSAL::DOES;
7             }
8              
9             {
10             package # hide from PAUSE
11             LINQ::Iterator::_LazyList;
12            
13             my $_throw_caller_error = sub {
14             shift;
15             require LINQ::Exception;
16             'LINQ::Exception::CallerError'->throw( message => @_ );
17             };
18            
19            
20             my $class = shift;
21             bless [
22             $_[0],
23             !!0,
24             [],
25 668     668   1167 ], $class;
26 668         2405 }
27            
28             my $self = shift;
29             my ( $ix ) = @_;
30             my $cache = $self->[__VALUES];
31            
32             $self->extend_to( $ix );
33            
34 1180     1180   3002 $ix >= @$cache ? undef : $cache->[$ix];
35 1180         1794 }
36 1180         1549
37             my $self = shift;
38 1180         2418 my ( $ix ) = @_;
39             my $cache = $self->[__VALUES];
40 1180 100       3903
41             $self->extend_to( $ix );
42            
43             return if $ix > 0+ $#$cache;
44 1532     1532   2012 return if $ix < 0 - @$cache;
45 1532         2369 \( $cache->[$ix] );
46 1532         2078 } #/ sub fetch_ref
47            
48 1532         3338 my $self = shift;
49             $self->extend_to( -1 );
50 1530 100       3276 scalar @{ $self->[__VALUES] };
51 1367 100       2588 }
52 1365         2321
53             my $self = shift;
54             scalar @{ $self->[__VALUES] };
55             }
56 856     856   43762
57 856         1947 my $self = shift;
58 839         1291 $self->[__EXHAUSTED];
  839         2543  
59             }
60            
61             require LINQ;
62 2     2   5
63 2         3 my $self = shift;
  2         11  
64             my ( $ix ) = @_;
65             my $cache = $self->[__VALUES];
66            
67 1     1   2 EXTEND: {
68 1         4 return if $self->[__EXHAUSTED];
69             return if $ix >= 0 && $ix < @$cache;
70            
71             my @got = $self->[__GENERATOR]->();
72 3568     3568   12005 my $got;
73            
74 3568         4871 # Crazy optimized loop to find and handle LINQ::END
75 3568         5077 # within @got
76 3568         4787 # uncoverable condition count:1
77             # uncoverable condition count:5
78             push( @$cache, shift @got )
79 3568 100       4480 and ref( $got = $cache->[-1] )
  5815         10745  
80 3966 100 100     10416 and $got == LINQ::END()
81             and ( $self->[__EXHAUSTED] = !!1 )
82 2724         5291 and pop( @$cache )
83 2707         8514 and (
84             @got
85             ? $self->$_throw_caller_error( 'Returned values after LINQ::END' )
86             : return ()
87             ) while @got;
88            
89 2707 100 66     13919 redo EXTEND;
      100        
      100        
      66        
      33        
90             } #/ EXTEND:
91             } #/ sub extend_to
92             }
93              
94              
95             our $AUTHORITY = 'cpan:TOBYINK';
96             our $VERSION = '0.003';
97              
98             use Role::Tiny::With ();
99             use LINQ::Util::Internal ();
100 2247         3834  
101             Role::Tiny::With::with( qw( LINQ::Collection ) );
102              
103             my $class = shift;
104             if ( @_ ) {
105             tie my ( @arr ), 'LINQ::Iterator::_LazyList',
106             LINQ::Util::Internal::assert_code( @_ );
107             return bless \@arr, $class;
108             }
109             LINQ::Util::Internal::throw(
110 100     100   26032 "CallerError",
  100         302404  
  100         2402  
111 100     100   24958 message => "Expected a coderef"
  100         282  
  100         14305  
112             );
113             } #/ sub new
114              
115             my $self = shift;
116 538     538 1 11861 tied( @$self );
117 538 100       1335 }
118 537         1340  
119             my $self = shift;
120 537         2975 my @list = @$self;
121            
122             # We must have exhausted the iterator now,
123 1         6 # so remove all the magic and act like a
124             # plain old arrayref.
125             #
126             if ( tied( @$self ) ) {
127             no warnings;
128             untie( @$self );
129 433     433   2145 @$self = @list;
130 433         1642 }
131            
132             @list;
133             } #/ sub to_list
134 266     266 1 626  
135 266         921  
136             my $self = shift;
137            
138             if ( my $guts = $self->_guts ) {
139             tie ( my @tied, 'LINQ::Iterator::_LazyList', undef );
140             @{ tied( @tied ) } = @$guts;
141 249 100       914 return \@tied;
142 100     100   730 }
  100         196  
  100         35542  
143 184         1301
144 184         551 $self->LINQ::Collection::to_array( @_ );
145             }
146              
147 249         1184 my $self = shift;
148            
149             if ( my $guts = $self->_guts ) {
150             my $ref = $guts->fetch_ref( @_ );
151             return $$ref if $ref;
152 134     134 1 27732 require LINQ::Exception;
153             'LINQ::Exception::NotFound'->throw( collection => $self );
154 134 100       285 }
155 131         322
156 131         362 $self->LINQ::Collection::element_at( @_ );
  131         420  
157 131         971 } #/ sub element_at
158              
159             my $self = shift;
160 3         15
161             if ( my $guts = $self->_guts ) {
162             my $idx = 0;
163             my $done = 0;
164 61     61 1 1514 return sub {
165             return if $done;
166 61 100       165 my $val = $guts->fetch_ref( $idx++ );
167 27         57 return $$val if $val;
168 27 100       101 ++$done;
169 4         954 return;
170 4         20 };
171             } #/ if ( my $guts = $self->...)
172            
173 34         146 $self->LINQ::Collection::to_iterator( @_ );
174             } #/ sub to_iterator
175              
176             1;
177 233     233 1 405  
178              
179 233 100       517 =pod
180 231         347  
181 231         368 =encoding utf-8
182              
183 1506 100   1506   2636 =head1 NAME
184 1505         2936  
185 1503 100       4064 LINQ::Iterator - a LINQ collection with an iterator backend
186 161         269  
187 161         420 =head1 SYNOPSIS
188 231         1154  
189             use LINQ qw( LINQ );
190             use LINQ::Iterator;
191 2         8
192             my $linq = LINQ( sub { ... } );
193            
194             # Same:
195             my $linq = 'LINQ::Iterator'->new( sub { ... } );
196              
197             =head1 METHODS
198              
199             LINQ::Iterator supports all the methods defined in L<LINQ::Collection>.
200              
201             =begin trustme
202              
203             =item new
204              
205             =item element_at
206              
207             =item to_list
208              
209             =item to_array
210              
211             =item to_iterator
212              
213             =end trustme
214              
215             =head1 BUGS
216              
217             Please report any bugs to
218             L<http://rt.cpan.org/Dist/Display.html?Queue=LINQ>.
219              
220             =head1 SEE ALSO
221              
222             L<LINQ>, L<LINQ::Collection>.
223              
224             L<https://en.wikipedia.org/wiki/Language_Integrated_Query>
225              
226             =head1 AUTHOR
227              
228             Toby Inkster E<lt>tobyink@cpan.orgE<gt>.
229              
230             =head1 COPYRIGHT AND LICENCE
231              
232             This software is copyright (c) 2021 by Toby Inkster.
233              
234             This is free software; you can redistribute it and/or modify it under
235             the same terms as the Perl 5 programming language system itself.
236              
237             =head1 DISCLAIMER OF WARRANTIES
238              
239             THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
240             WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
241             MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.