File Coverage

blib/lib/Catmandu/Iterable.pm
Criterion Covered Total %
statement 260 261 99.6
branch 67 72 93.0
condition 26 31 83.8
subroutine 56 56 100.0
pod 33 34 97.0
total 442 454 97.3


line stmt bran cond sub pod time code
1              
2             use Catmandu::Sane;
3 64     64   125181  
  64         131  
  64         440  
4             our $VERSION = '1.2018';
5              
6             use Catmandu::Util qw(
7 64         4603 is_number
8             is_value
9             is_string
10             is_array_ref
11             is_hash_ref
12             is_regex_ref
13             is_same
14             check_positive
15             );
16 64     64   438 use Time::HiRes qw(gettimeofday tv_interval);
  64         145  
17 64     64   368 use Hash::Util::FieldHash qw(fieldhash);
  64         127  
  64         573  
18 64     64   36169 use Role::Tiny;
  64         51076  
  64         3329  
19 64     64   425 use namespace::clean;
  64         145  
  64         474  
20 64     64   12674  
  64         126  
  64         414  
21             # delay loading these because of circular dependency
22             require Catmandu::Iterator;
23             require Catmandu::ArrayIterator;
24              
25             requires 'generator';
26              
27             {
28             # can't use Moo attribute because of circular dependency
29             fieldhash my %_generators;
30              
31             my ($self) = @_;
32             ($_generators{$self} ||= $self->generator)->();
33 9     9 1 1942 }
34 9   66     50  
35             my ($self) = @_;
36             $_generators{$self} = $self->generator;
37             }
38 4     4 1 360 }
39 4         13  
40             my ($self) = @_;
41             my $next = $self->generator;
42             my @a;
43             my $data;
44 87     87 1 9048 while (defined($data = $next->())) {
45 87         780 push @a, $data;
46 87         197 }
47             \@a;
48 87         178 }
49 911         2017  
50             my ($self) = @_;
51 87         1408 my $next = $self->generator;
52             my $n = 0;
53             while ($next->()) {
54             $n++;
55 15     15 1 400 }
56 15         65 $n;
57 15         52 }
58 15         49  
59 1026         1809 my ($self, $start, $total) = @_;
60             $start //= 0;
61 15         132 Catmandu::Iterator->new(
62             sub {
63             sub {
64             if (defined $total) {
65 6     6 1 29 $total || return;
66 6   100     20 }
67             state $next = $self->generator;
68             state $data;
69             while (defined($data = $next->())) {
70 13 100       33 if ($start > 0) {
71 9 100       28 $start--;
72             next;
73 9         39 }
74 9         30 if (defined $total) {
75 9         19 $total--;
76 12 100       46 }
77 4         8 return $data;
78 4         11 }
79             return;
80 8 100       34 }
81 5         10 }
82             );
83 8         33 }
84              
85 1         5 my ($self, $sub) = @_;
86             my $next = $self->generator;
87 6     6   22 my $n = 0;
88 6         50 my $data;
89             while (defined($data = $next->())) {
90             $sub->($data);
91             $n++;
92 5     5 1 56 }
93 5         69 $n;
94 5         14 }
95 5         10  
96 5         11 my ($self, $sub) = @_;
97 9         34 my $next = $self->generator;
98 8         22 my $n = 0;
99             my $data;
100 4         28 while (defined($data = $next->())) {
101             $sub->($data) || last;
102             $n++;
103             }
104 1     1 0 2 $n;
105 1         3 }
106 1         3  
107 1         1 my ($self, $sub) = @_;
108 1         3 Catmandu::Iterator->new(
109 2 100       6 sub {
110 1         537 sub {
111             state $next = $self->generator;
112 1         541 state $data;
113             if (defined($data = $next->())) {
114             $sub->($data);
115             return $data;
116 10     10 1 572 }
117             return;
118             }
119             }
120 30         98 );
121 30         64 }
122 30 100       57  
123 20         87 my ($self, $n, $sub) = @_;
124 20         66 check_positive($n);
125             Catmandu::Iterator->new(
126 10         43 sub {
127             sub {
128 10     10   50 state $next = $self->generator;
129 10         91 state $data;
130             state $i = 0;
131             if (defined($data = $next->())) {
132             if (++$i == $n) {
133 3     3 1 623 $sub->($data);
134 3         10 $i = 0;
135             }
136             return $data;
137             }
138 22         28 return;
139 22         39 }
140 22         23 }
141 22 100       29 );
142 20 100       61 }
143 8         26  
144 8         18 my ($self, $sub) = @_;
145             my $next = $self->generator;
146 20         34 my $data;
147             while (defined($data = $next->())) {
148 2         9 $sub->($data) && return 1;
149             }
150 2     2   8 return 0;
151 2         18 }
152              
153             my ($self, $sub) = @_;
154             my $next = $self->generator;
155 8     8 1 19 my $n = 0;
156 8         22 my $data;
157 8         56 while (defined($data = $next->())) {
158 8         16 $sub->($data) && ++$n > 1 && return 1;
159 21 100       474 }
160             return 0;
161 4         250 }
162              
163             my ($self, $sub) = @_;
164             my $next = $self->generator;
165 2     2 1 6 my $data;
166 2         6 while (defined($data = $next->())) {
167 2         15 $sub->($data) || return 0;
168 2         3 }
169 2         6 return 1;
170 5 100 100     33 }
171              
172 1         9 my ($self, $sub) = @_;
173             Catmandu::Iterator->new(
174             sub {
175             sub {
176 3     3 1 9 state $next = $self->generator;
177 3         20 state @buff;
178 3         22 @buff = $sub->($next->() // return) unless @buff;
179 3         9 shift @buff;
180 5 100       34 }
181             }
182 2         20 );
183             }
184              
185             my $self = shift;
186 27     27 1 78 my $memo_set = @_ > 1;
187             my $sub = pop;
188             my $memo = shift;
189             my $next = $self->generator;
190 803         1251 my $data;
191 803         921 while (defined($data = $next->())) {
192 803 100 100     2490 if ($memo_set) {
193 778         2239 $memo = $sub->($memo, $data);
194             }
195 26     26   105 else {
196 27         202 $memo = $data;
197             $memo_set = 1;
198             }
199             }
200 26     26 1 155 $memo;
201 26         52 }
202 26         42  
203 26         35 $_[0]->generator->();
204 26         249 }
205 26         123  
206 26         58 $_[0]->slice(1);
207 95 100       256 }
208 94         158  
209             $_[0]->slice(0, $_[1]);
210             }
211 1         2  
212 1         68 {
213             my $to_sub = sub {
214             my ($arg1, $arg2) = @_;
215 26         569  
216             if (is_string($arg1)) {
217             if (is_regex_ref($arg2)) {
218             return sub {
219 12     12 1 216 is_hash_ref($_[0]) || return 0;
220             my $val = $_[0]->{$arg1};
221             is_value($val) && $val =~ $arg2;
222             };
223 2     2 1 558 }
224             if (is_array_ref($arg2)) {
225             return sub {
226             is_hash_ref($_[0]) || return 0;
227 2     2 1 7 is_value(my $val = $_[0]->{$arg1}) || return 0;
228             for my $v (@$arg2) {
229             return 1 if $val eq $v;
230             }
231             0;
232             };
233             }
234             return sub {
235             is_hash_ref($_[0]) || return 0;
236             my $val = $_[0]->{$arg1};
237             is_value($val) && $val eq $arg2;
238             };
239             }
240              
241             if (is_regex_ref($arg1)) {
242             return sub {
243             my $val = $_[0];
244             is_value($val) && $val =~ $arg1;
245             };
246             }
247              
248             $arg1;
249             };
250              
251             my $self = shift;
252             my $sub = $to_sub->(@_);
253             my $next = $self->generator;
254             my $data;
255             while (defined($data = $next->())) {
256             $sub->($data) && return $data;
257             }
258             return;
259             }
260              
261             my $self = shift;
262             my $sub = $to_sub->(@_);
263             Catmandu::Iterator->new(
264             sub {
265             sub {
266             state $next = $self->generator;
267             state $data;
268             while (defined($data = $next->())) {
269             $sub->($data) && return $data;
270 4     4 1 9 }
271 4         10 return;
272 4         11 }
273 4         30 }
274 4         8 );
275 8 100       43 }
276              
277 1         9  
278             my $self = shift;
279             my $sub = $to_sub->(@_);
280             Catmandu::Iterator->new(
281 10     10 1 26 sub {
282 10         25 sub {
283             state $next = $self->generator;
284             state $data;
285             while (defined($data = $next->())) {
286 27         66 $sub->($data) || return $data;
287 27         74 }
288 27         47 return;
289 31 100       119 }
290             }
291 10         42 );
292             }
293 10     10   31 };
294 10         56  
295             my ($self, $cmp) = @_;
296             if (!defined $cmp) {
297 4     4 1 13 Catmandu::ArrayIterator->new([sort @{$self->to_array}]);
298             }
299             elsif (ref $cmp) {
300 13     13 1 29 Catmandu::ArrayIterator->new(
301 13         41 [sort {$cmp->($a, $b)} @{$self->to_array}]);
302             }
303             else {
304             # TODO: use Schwartzian transform for more complex key
305 36         280 Catmandu::ArrayIterator->new(
306 36         72 [sort {$a->{$cmp} cmp $b->{$cmp}} @{$self->to_array}]);
307 36         66 }
308 35 100       104 }
309              
310 11         51 my ($self, $key) = @_;
311             $self->map(
312 12     12   61 sub {
313 13         66 $_[0]->{$key};
314             }
315             );
316             }
317              
318 3     3 1 7 my ($self, $method, @args) = @_;
319 3 100       13 $self->map(
    100          
320 1         3 sub {
  1         13  
321             $_[0]->$method(@args);
322             }
323             );
324 1         3 }
  3         8  
  1         3  
325              
326              
327             my ($self, $data) = @_;
328             $self->any(
329 1         3 sub {
  2         13  
  1         4  
330             is_same($data, $_[0]);
331             }
332             );
333             }
334 2     2 1 13  
335             my ($self, $size) = @_;
336             Catmandu::Iterator->new(
337 6     6   20 sub {
338             sub {
339 2         15 state $next = $self->generator;
340              
341             my $group = [];
342              
343 5     5 1 65 for (my $i = 0; $i < $size; $i++) {
344             push @$group, $next->() // last;
345             }
346 16     16   853  
347             unless (@$group) {
348 5         19 return;
349             }
350              
351 4     4 1 15 Catmandu::ArrayIterator->new($group);
352             }
353             }
354 6     6 1 14 );
355             }
356              
357 17     17   39 my @iterators = @_;
358             Catmandu::Iterator->new(
359 6         27 sub {
360             sub {
361             state @generators;
362             state $n = @iterators;
363 3     3 1 16 state $i = 0;
364             while ($n) {
365             $i = 0 if $i == $n;
366             my $next = $generators[$i] ||= $iterators[$i]->generator;
367 17         34 if (defined(my $data = $next->())) {
368             $i++;
369 17         40 return $data;
370             }
371 17         32 else {
372 24   100     55 splice @generators, $i, 1;
373             $n--;
374             }
375 17 100       75 }
376 3         9 return;
377             }
378             }
379 14         38 );
380             }
381 3     3   31  
382 3         21 my ($self, $sub) = @_;
383             $self->reduce(
384             undef,
385             sub {
386 4     4 1 72 my ($memo, $data) = @_;
387             my $val = defined $sub ? $sub->($data) : $data;
388             return $val > $memo ? $val : $memo
389             if is_number($memo) && is_number($val);
390 26         29 return $memo if is_number($memo);
391 26         30 return $val if is_number($val);
392 26         29 return;
393 26         37 }
394 30 100       43 );
395 30   66     60 }
396 30 100       108  
397 22         63 my ($self, $sub) = @_;
398 22         40 $_[0]->reduce(
399             undef,
400             sub {
401 8         29 my ($memo, $data) = @_;
402 8         22 my $val = defined $sub ? $sub->($data) : $data;
403             return $val < $memo ? $val : $memo
404             if is_number($memo) && is_number($val);
405 4         8 return $memo if is_number($memo);
406             return $val if is_number($val);
407 4     4   21 return;
408 4         19 }
409             );
410             }
411              
412 5     5 1 18 my ($self) = @_;
413             $self->tap(
414             sub {
415             state $n = 0;
416 12     12   29 state $t = [gettimeofday];
417 12 100       24 if (++$n % 100 == 0) {
418 12 50 100     86 printf STDERR "added %9d (%d/sec)\n", $n,
    100          
419             $n / tv_interval($t);
420 7 100       18 }
421 5 100       15 }
422 3         7 );
423             }
424 5         24  
425             my ($self, %opts) = @_;
426             $opts{header} //= 1;
427             $opts{col_sep} //= " | ";
428 5     5 1 12 my @cols = $opts{cols} ? @{$opts{cols}} : ();
429             my @col_lengths = map length, @cols;
430              
431             my $rows = $self->map(
432 12     12   19 sub {
433 12 100       33 my $data = $_[0];
434 12 50 100     55 my $row = [];
    100          
435             for (my $i = 0; $i < @cols; $i++) {
436 7 100       14 my $col = $data->{$cols[$i]} // "";
437 5 100       15 my $len = length $col;
438 3         6 $col_lengths[$i] = $len if $len > $col_lengths[$i];
439             push @$row, $col;
440 5         26 }
441             $row;
442             }
443             )->to_array;
444 6     6 1 18  
445             my @indices = 0 .. @cols - 1;
446             my $pattern
447 14     14   28 = join($opts{col_sep}, map {"%-$col_lengths[$_]s"} @indices) . "\n";
448 14         40  
449 14 50       41 if ($opts{header}) {
450 0         0 printf $pattern, @cols;
451             my $sep = $opts{col_sep};
452             $sep =~ s/[^|]/-/g;
453             print join($sep, map {'-' x $col_lengths[$_]} @indices) . "\n";
454 6         53 }
455             for my $row (@$rows) {
456             printf $pattern, @$row;
457             }
458 6     6 1 21 }
459 6   50     28  
460 6   50     36 my ($self, $sub) = @_;
461 6 50       14 Catmandu::Iterator->new(
  6         17  
462 6         22 sub {
463             sub {
464             state $next = $self->generator;
465             my $data = $next->() // return;
466 717     717   13754 $sub->($data) && return;
467 717         1051 $data;
468 717         1643 }
469 2151   100     4270 }
470 2151         2869 );
471 2151 100       3251 }
472 2151         4443  
473             my ($self) = @_;
474 717         1397 my $next = $self->generator;
475             my $run = 0;
476 6         44 while (defined($next->())) {
477             $run ||= 1;
478 6         75 }
479             $run;
480 6         18 }
  18         74  
481              
482 6 50       24 1;
483 6         42  
484 6         164  
485 6         33 =pod
486 6         17  
  18         59  
487             =head1 NAME
488 6         76  
489 717         11537 Catmandu::Iterable - Base role for all iterable Catmandu classes
490              
491             =head1 SYNOPSIS
492              
493             # Create an example Iterable using the Catmandu::Importer::Mock class
494 2     2 1 6 my $it = Catmandu::Importer::Mock->new(size => 10);
495              
496             my $array_ref = $it->to_array;
497             my $num = $it->count;
498 5         9  
499 5   50     21 # Loop functions
500 5 100       20 $it->each(sub { print shift->{n} });
501 3         15  
502             my $item = $it->first;
503 2     2   7  
504 2         12 $it->rest
505             ->each(sub { print shift->{n} });
506              
507             $it->slice(3,2)
508 5     5 1 11 ->each(sub { print shift->{n} });
509 5         12  
510 5         24 $it->take(5)
511 5         7 ->each(sub { print shift->{n} });
512 24   100     51  
513             $it->group(5)
514 5         50 ->each(sub { printf "group of %d items\n" , shift->count});
515              
516             $it->tap(\&logme)->tap(\&printme)->tap(\&mailme)
517             ->each(sub { print shift->{n} });
518              
519             my $titles = $it->pluck('title')->to_array;
520              
521             # Select and loop
522             my $item = $it->detect(sub { shift->{n} > 5 });
523              
524             $it->select(sub { shift->{n} > 5})
525             ->each(sub { print shift->{n} });
526              
527             $it->reject(sub { shift->{n} > 5})
528             ->each(sub { print shift->{n} });
529              
530             # Boolean
531             if ($it->any(sub { shift->{n} > 5}) {
532             .. at least one n > 5 ..
533             }
534              
535             if ($it->many(sub { shift->{n} > 5}) {
536             .. at least two n > 5 ..
537             }
538              
539             if ($it->all(sub { shift->{n} > 5}) {
540             .. all n > 5 ..
541             }
542              
543             # Modify and summary
544             my $it2 = $it->map(sub { shift->{n} * 2 });
545              
546             my $sum = $it2->reduce(0,sub {
547             my ($prev,$this) = @_;
548             $prev + $this;
549             });
550              
551             my $it3 = $it->group(2)->invoke('to_array');
552              
553             # Calculate maximum of 'n' field
554             my $max = $it->max(sub {
555             shift->{n};
556             });
557              
558             # Calculate minimum of 'n' field
559             my $in = $it->min(sub {
560             shift->{n};
561             });
562              
563             =head1 DESCRIPTION
564              
565             The Catmandu::Iterable class provides many list methods to Iterators such as Importers and
566             Exporters. Most of the methods are lazy if the underlying datastream supports it. Beware of
567             idempotence: many iterators contain state information and calls will give different results on
568             a second invocation.
569              
570             =head1 METHODS
571              
572             =head2 to_array
573              
574             Return all the items in the iterator as an array ref.
575              
576             =head2 count
577              
578             Return the count of all the items in the iterator.
579              
580             =head3 LOOPING
581              
582             =head2 each(\&callback)
583              
584             For each item in the iterator execute the callback function with the item as
585             first argument. Returns the number of items in the iterator.
586              
587             =head2 first
588              
589             Return the first item from the iterator.
590              
591             =head2 rest
592              
593             Returns an iterator containing everything except the first item.
594              
595             =head2 slice($index,$length)
596              
597             Returns an new iterator starting at the item at C<$index> returning at most <$length> items.
598              
599             =head2 take($num)
600              
601             Returns an iterator with the first C<$num> items.
602              
603             =head2 group($num)
604              
605             Splits the iterator into new iterators each containing C<$num> items.
606              
607             $it->group(500)->each(sub {
608             my $group_it = $_[0];
609             $group_it->each(sub {
610             my $item = $_[0];
611             # ...
612             });
613             });
614              
615             Note that the group iterators load their items in memory. The last group
616             iterator will contain less than C<$num> item unless the item count is divisible
617             by C<$num>.
618              
619             =head2 interleave(@iterators)
620              
621             Returns an iterator which returns the first item of each iterator then the
622             second of each and so on.
623              
624             =head2 contains($data)
625              
626             Alias for C<includes>.
627              
628             =head2 includes($data)
629              
630             return true if any item in the collection is deeply equal to C<$data>.
631              
632             =head2 tap(\&callback)
633              
634             Returns a copy of the iterator and executing callback on each item. This method works
635             like the Unix C<tee> command. Use this command to peek into an iterable while it is
636             processing results. E.g. you are writing code to process an iterable and wrote
637             something like:
638              
639             $it->each(sub {
640             # Very complicated routine
641             ...
642             });
643              
644             Now you would like to benchmark this piece of code (how fast are we processing).
645             This can be done by tapping into the iterator and calling a 'benchmark' subroutine
646             in your program that for instance counts the number of items divided by the
647             execution time.
648              
649             $it->tap(\&benchmark)->each(sub {
650             # Very complicated routine
651             ...
652             });
653              
654             sub benchmark {
655             my $item = shift;
656             $start ||= time;
657             $count++;
658              
659             printf "%d recs/sec\n" , $count/(time - $start + 1) if $count % 100 == 0;
660             }
661              
662             Note that the C<benchmark> method already implements this common case.
663              
664             =head2 every($num, \&callback)
665              
666             Similar to C<tap>, but only calls the callback every C<$num> times. Useful for
667             benchmarking and sampling.
668              
669             =head2 detect(\&callback)
670              
671             Returns the first item for which callback returns a true value.
672              
673             =head2 detect(qr/..../)
674              
675             If the iterator contains STRING values, then return the first item which matches the
676             regex.
677              
678             =head2 detect($key => $val)
679              
680             If the iterator contains HASH values, then return the first item where the value of
681             C<$key> is equal to C<$val>.
682              
683             =head2 detect($key => qr/..../)
684              
685             If the iterator contains HASH values, then return the first item where the value of
686             C<$key> matches the regex.
687              
688             =head2 detect($key => [$val, ...])
689              
690             If the iterator contains HASH values, then return the first item where the value of
691             C<$key> is equal to any of the values given.
692              
693             =head2 pluck($key)
694              
695             Return an iterator that only contains the values of the given C<$key>.
696              
697             =head2 select(\&callback)
698              
699             Returns an iterator containing only items item for which the callback returns a true value.
700              
701             =head2 select(qr/..../)
702              
703             If the iterator contains STRING values, then return each item which matches the regex.
704              
705             =head2 select($key => $val)
706              
707             If the iterator contains HASH values, then return each item where the value of
708             C<$key> is equal to C<$val>.
709              
710             =head2 select($key => qr/..../)
711              
712             If the iterator contains HASH values, then return each item where the value of C<$key>
713             matches the regex.
714              
715             =head2 select($key => [$val, ...])
716              
717             If the iterator contains HASH values, then return each item where the value of
718             C<$key> is equal to any of the vals given.
719              
720             =head2 grep( ... )
721              
722             Alias for C<select( ... )>.
723              
724             =head2 reject(\&callback)
725              
726             Returns an iterator containing each item for which callback returns a false value.
727              
728             =head2 reject(qr/..../)
729              
730             If the iterator contains STRING values, then reject every item except those
731             matching the regex.
732              
733             =head2 reject($key => qr/..../)
734              
735             If the iterator contains HASH values, then reject every item for where the value of C<$key>
736             DOESN'T match the regex.
737              
738             =head2 reject($key => $val)
739              
740             If the iterator contains HASH values, then return each item where the value of
741             C<$key> is NOT equal to C<$val>.
742              
743             =head2 reject($key => [$val, ...])
744              
745             If the iterator contains HASH values, then return each item where the value of
746             C<$key> is NOT equal to any of the values given.
747              
748             =head2 sorted
749              
750             Returns an iterator with items sorted lexically. Note that sorting requires
751             memory because all items are buffered in a L<Catmandu::ArrayIterator>.
752              
753             =head2 sorted(\&callback)
754              
755             Returns an iterator with items sorted by a callback. The callback is expected to
756             returns an integer less than, equal to, or greater than C<0>. The following code
757             snippets result in equal arrays:
758              
759             $iterator->sorted(\&callback)->to_array
760             [ sort \&callback @{ $iterator->to_array } ]
761              
762             =head2 sorted($key)
763              
764             Returns an iterator with items lexically sorted by a key. This is equivalent to
765             sorting with the following callback:
766              
767             $iterator->sorted(sub { $_[0]->{$key} cmp $_[1]->{$key} })
768              
769             =head3 EXTERNAL ITERATOR
770              
771             L<Catmandu::Iterable> behaves like an internal iterator. C<next> and C<rewind>
772             allow you to use it like an external iterator.
773              
774             =head2 next
775              
776             Each call to C<next> will return the next item until the iterator is exhausted,
777             then it will keep returning C<undef>.
778              
779             while (my $data = $it->next) {
780             # do stuff
781             }
782              
783             $it->next; # returns undef
784              
785             =head2 rewind
786              
787             Rewind the external iterator to the first item.
788              
789             $it->next; # => {n => 1}
790             $it->next; # => {n => 2}
791             $it->next; # => {n => 3}
792             $it->rewind
793             $it->next; # => {n => 1}
794              
795             Note the the iterator must support this behavior. Many importers are not
796             rewindable.
797              
798             =head3 BOOLEAN FUNCTIONS
799              
800             =head2 any(\&callback)
801              
802             Returns true if at least one item generates a true value when executing callback.
803              
804             =head2 many(\&callback)
805              
806             Alias for C<many>.
807              
808             =head2 many(\&callback)
809              
810             Returns true if at least two items generate a true value when executing callback.
811              
812             =head2 all(\&callback)
813              
814             Returns true if all the items generate a true value when executing callback.
815              
816             =head3 MAP & REDUCE
817              
818             =head2 map(\&callback)
819              
820             Returns a new iterator containing for each item the result of the callback. If
821             the callback returns multiple or no items, the resulting iterator will grow or
822             shrink.
823              
824             =head2 reduce([$start],\&callback)
825              
826             For each item in the iterator execute C<&callback($prev,$item)> where C<$prev> is the
827             optional C<$start> value or the result of the previous call to callback. Returns the
828             final result of the callback function.
829              
830             =head2 invoke($name)
831              
832             Returns an interator were the method C<$name> is called on every object in the iterable.
833             This is a shortcut for C<$it->map(sub { $_[0]->$name })>.
834              
835             =head2 max()
836              
837             Returns the maximum of an iterator containing only numbers.
838              
839             =head2 max(\&callback)
840              
841             Returns the maximum of the numbers returned by executing callback.
842              
843             =head2 min()
844              
845             Returns the minimum of an iterator containing only numbers.
846              
847             =head2 min(\&callback)
848              
849             Returns the minimum of the numbers returned by executing callback.
850              
851             =head2 benchmark()
852              
853             Prints the number of records processed per second to STDERR.
854              
855             =head2 format(cols => ['key', ...], col_sep => ' | ', header => 1|0)
856              
857             Print the iterator data formatted as a spreadsheet like table. Note that this
858             method will load the whole dataset in memory to calculate column widths. See
859             also L<Catmandu::Exporter::Table> for a more elaborated method of printing
860             iterators in tabular form.
861              
862             =head2 stop_if(\&callback)
863              
864             Returns a new iterator thats stops processing if the callback returns false.
865              
866             # stop after encountering 3 frobnitzes
867             my $frobnitzes = 0;
868             $iterator->stop_if(sub {
869             my $rec = shift;
870             $frobnitzes++ if $rec->{title} =~ /frobnitz/;
871             $frobnitzes > 3;
872             })->each(sub {
873             my $rec = shift;
874             ...
875             });
876              
877             =head2 run
878              
879             Simply invokes the iterator and returns 1 if any records were processed, 0 otherwise.
880              
881             $it = $it->tap(sub {
882             # do something
883             });
884             $it = $it->tap(sub {
885             # do another thing
886             });
887             $it->run
888              
889             print 'not empty' if $it->run;
890              
891             =head1 SEE ALSO
892              
893             L<Catmandu::Iterator>.
894              
895             =cut