Filename | /home/ss5/perl5/perlbrew/perls/tapper-perl/lib/site_perl/5.16.3/Iterator/Util.pm |
Statements | Executed 124 statements in 1.44ms |
Calls | P | F | Exclusive Time |
Inclusive Time |
Subroutine |
---|---|---|---|---|---|
1 | 1 | 1 | 655µs | 749µs | BEGIN@20 | Iterator::Util::
1 | 1 | 1 | 644µs | 7.59ms | BEGIN@28 | Iterator::Util::
17 | 2 | 1 | 185µs | 4.44ms | __ANON__[:52] | Iterator::Util::
4 | 1 | 1 | 57µs | 1.34ms | imap | Iterator::Util::
4 | 1 | 1 | 51µs | 216µs | iarray | Iterator::Util::
17 | 2 | 1 | 40µs | 2.32ms | __ANON__[:158] | Iterator::Util::
1 | 1 | 1 | 12µs | 22µs | BEGIN@15.4 | Data::DPath::Context::
1 | 1 | 1 | 9µs | 18µs | BEGIN@370 | Iterator::Util::
1 | 1 | 1 | 8µs | 18µs | BEGIN@284 | Iterator::Util::
1 | 1 | 1 | 7µs | 10µs | BEGIN@16.5 | Data::DPath::Context::
1 | 1 | 1 | 7µs | 40µs | BEGIN@21 | Iterator::Util::
1 | 1 | 1 | 7µs | 16µs | BEGIN@373 | Iterator::Util::
0 | 0 | 0 | 0s | 0s | __ANON__[:114] | Iterator::Util::
0 | 0 | 0 | 0s | 0s | __ANON__[:133] | Iterator::Util::
0 | 0 | 0 | 0s | 0s | __ANON__[:199] | Iterator::Util::
0 | 0 | 0 | 0s | 0s | __ANON__[:241] | Iterator::Util::
0 | 0 | 0 | 0s | 0s | __ANON__[:293] | Iterator::Util::
0 | 0 | 0 | 0s | 0s | __ANON__[:398] | Iterator::Util::
0 | 0 | 0 | 0s | 0s | __ANON__[:399] | Iterator::Util::
0 | 0 | 0 | 0s | 0s | __ANON__[:434] | Iterator::Util::
0 | 0 | 0 | 0s | 0s | __ANON__[:81] | Iterator::Util::
0 | 0 | 0 | 0s | 0s | iappend | Iterator::Util::
0 | 0 | 0 | 0s | 0s | igrep | Iterator::Util::
0 | 0 | 0 | 0s | 0s | ihead | Iterator::Util::
0 | 0 | 0 | 0s | 0s | ilist | Iterator::Util::
0 | 0 | 0 | 0s | 0s | ipairwise | Iterator::Util::
0 | 0 | 0 | 0s | 0s | irange | Iterator::Util::
0 | 0 | 0 | 0s | 0s | iskip | Iterator::Util::
0 | 0 | 0 | 0s | 0s | iskip_until | Iterator::Util::
0 | 0 | 0 | 0s | 0s | iuniq | Iterator::Util::
Line | State ments |
Time on line |
Calls | Time in subs |
Code |
---|---|---|---|---|---|
1 | =for gpg | ||||
2 | -----BEGIN PGP SIGNED MESSAGE----- | ||||
3 | Hash: SHA1 | ||||
4 | |||||
5 | =head1 NAME | ||||
6 | |||||
7 | Iterator::Util - Essential utilities for the Iterator class. | ||||
8 | |||||
9 | =head1 VERSION | ||||
10 | |||||
11 | This documentation describes version 0.02 of Iterator::Util, August 23, 2005. | ||||
12 | |||||
13 | =cut | ||||
14 | |||||
15 | 2 | 18µs | 2 | 32µs | # spent 22µs (12+10) within Data::DPath::Context::BEGIN@15.4 which was called:
# once (12µs+10µs) by Data::DPath::Context::BEGIN@19 at line 15 # spent 22µs making 1 call to Data::DPath::Context::BEGIN@15.4
# spent 10µs making 1 call to strict::import |
16 | 2 | 30µs | 2 | 13µs | # spent 10µs (7+3) within Data::DPath::Context::BEGIN@16.5 which was called:
# once (7µs+3µs) by Data::DPath::Context::BEGIN@19 at line 16 # spent 10µs making 1 call to Data::DPath::Context::BEGIN@16.5
# spent 3µs making 1 call to warnings::import |
17 | package Iterator::Util; | ||||
18 | 1 | 700ns | our $VERSION = '0.02'; | ||
19 | |||||
20 | 2 | 74µs | 2 | 804µs | # spent 749µs (655+94) within Iterator::Util::BEGIN@20 which was called:
# once (655µs+94µs) by Data::DPath::Context::BEGIN@19 at line 20 # spent 749µs making 1 call to Iterator::Util::BEGIN@20
# spent 55µs making 1 call to base::import |
21 | 2 | 38µs | 2 | 73µs | # spent 40µs (7+33) within Iterator::Util::BEGIN@21 which was called:
# once (7µs+33µs) by Data::DPath::Context::BEGIN@19 at line 21 # spent 40µs making 1 call to Iterator::Util::BEGIN@21
# spent 33µs making 1 call to vars::import |
22 | |||||
23 | 1 | 3µs | @EXPORT = qw(imap igrep irange ilist iarray ihead iappend | ||
24 | ipairwise iskip iskip_until imesh izip iuniq); | ||||
25 | |||||
26 | 1 | 1µs | @EXPORT_OK = (@EXPORT); | ||
27 | |||||
28 | 2 | 579µs | 1 | 7.59ms | # spent 7.59ms (644µs+6.94) within Iterator::Util::BEGIN@28 which was called:
# once (644µs+6.94ms) by Data::DPath::Context::BEGIN@19 at line 28 # spent 7.59ms making 1 call to Iterator::Util::BEGIN@28 |
29 | |||||
30 | # Function name: imap | ||||
31 | # Synopsis: $iter = imap {code} $another_iterator; | ||||
32 | # Description: Transforms an iterator. | ||||
33 | # Created: 07/27/2005 by EJR | ||||
34 | # Parameters: code - Transformation code | ||||
35 | # $another_iterator - any other iterator. | ||||
36 | # Returns: Transformed iterator. | ||||
37 | # Exceptions: Iterator::X::Parameter_Error | ||||
38 | # Iterator::X::Am_Now_Exhausted | ||||
39 | sub imap (&$) | ||||
40 | # spent 1.34ms (57µs+1.29) within Iterator::Util::imap which was called 4 times, avg 336µs/call:
# 4 times (57µs+1.29ms) by Data::DPath::Context::_iter at line 411 of Data/DPath/Context.pm, avg 336µs/call | ||||
41 | 4 | 4µs | my ($transformation, $iter) = @_; | ||
42 | |||||
43 | 4 | 22µs | 4 | 6µs | Iterator::X::Parameter_Error->throw(q{Argument to imap must be an Iterator object}) # spent 6µs making 4 calls to UNIVERSAL::isa, avg 2µs/call |
44 | unless UNIVERSAL::isa($iter, 'Iterator'); | ||||
45 | |||||
46 | return Iterator->new( sub | ||||
47 | # spent 4.44ms (185µs+4.25) within Iterator::Util::__ANON__[/home/ss5/perl5/perlbrew/perls/tapper-perl/lib/site_perl/5.16.3/Iterator/Util.pm:52] which was called 17 times, avg 261µs/call:
# 13 times (126µs+3.14ms) by Iterator::value at line 227 of Iterator.pm, avg 251µs/call
# 4 times (58µs+1.11ms) by Iterator::_initialize at line 168 of Iterator.pm, avg 293µs/call | ||||
48 | 17 | 29µs | 21 | 1.58ms | Iterator::is_done if ($iter->is_exhausted); # spent 1.54ms making 4 calls to Iterator::is_done, avg 386µs/call
# spent 32µs making 17 calls to Iterator::is_exhausted, avg 2µs/call |
49 | |||||
50 | 13 | 26µs | 13 | 1.07ms | local $_ = $iter->value (); # spent 2.60ms making 13 calls to Iterator::value, avg 200µs/call, recursion: max depth 1, sum of overlapping time 1.52ms |
51 | 13 | 58µs | 13 | 79µs | return $transformation-> (); # spent 79µs making 13 calls to Data::DPath::Context::__ANON__[Data/DPath/Context.pm:411], avg 6µs/call |
52 | 4 | 34µs | 4 | 1.28ms | }); # spent 1.28ms making 4 calls to Iterator::new, avg 320µs/call |
53 | } | ||||
54 | |||||
55 | |||||
56 | # Function name: igrep | ||||
57 | # Synopsis: $iter = igrep {code} $another_iterator; | ||||
58 | # Description: Filters an iterator. | ||||
59 | # Created: 07/27/2005 by EJR | ||||
60 | # Parameters: code - Filter condition. | ||||
61 | # $another_iterator - any other iterator. | ||||
62 | # Returns: Filtered iterator. | ||||
63 | # Exceptions: Iterator::X::Parameter_Error | ||||
64 | # Iterator::X::Am_Now_Exhausted | ||||
65 | sub igrep (&$) | ||||
66 | { | ||||
67 | my ($test, $iter) = @_; | ||||
68 | |||||
69 | Iterator::X::Parameter_Error->throw(q{Argument to imap must be an Iterator object}) | ||||
70 | unless UNIVERSAL::isa($iter, 'Iterator'); | ||||
71 | |||||
72 | return Iterator->new(sub | ||||
73 | { | ||||
74 | while ($iter->isnt_exhausted ()) | ||||
75 | { | ||||
76 | local $_ = $iter->value (); | ||||
77 | return $_ if $test-> (); | ||||
78 | } | ||||
79 | |||||
80 | Iterator::is_done(); | ||||
81 | }); | ||||
82 | } | ||||
83 | |||||
84 | |||||
85 | # Function name: irange | ||||
86 | # Synopsis: $iter = irange ($start, $end, $step); | ||||
87 | # Description: Generates an arithmetic sequence of numbers. | ||||
88 | # Created: 07/27/2005 by EJR | ||||
89 | # Parameters: $start - First value. | ||||
90 | # $end - Final value. (may be omitted) | ||||
91 | # $step - Increment value. (may be omitted) | ||||
92 | # Returns: Sequence iterator | ||||
93 | # Exceptions: Iterator::X::Am_Now_Exhausted | ||||
94 | # Notes: If the $end value is omitted, iterator is unbounded. | ||||
95 | # If $step is omitted, it defaults to 1. | ||||
96 | # $step may be negative (or even zero). | ||||
97 | sub irange | ||||
98 | { | ||||
99 | my ($from, $to, $step) = @_; | ||||
100 | $step = 1 unless defined $step; | ||||
101 | |||||
102 | return Iterator->new (sub | ||||
103 | { | ||||
104 | # Reached limit? | ||||
105 | Iterator::is_done | ||||
106 | if (defined($to) | ||||
107 | && ($step>0 && $from>$to || $step<0 && $from<$to) ); | ||||
108 | |||||
109 | # This iteration's return value | ||||
110 | my $retval = $from; | ||||
111 | |||||
112 | $from += $step; | ||||
113 | return $retval; | ||||
114 | }); | ||||
115 | } | ||||
116 | |||||
117 | # Function name: ilist | ||||
118 | # Synopsis: $iter = ilist (@list); | ||||
119 | # Description: Creates an iterator from a list | ||||
120 | # Created: 07/28/2005 by EJR | ||||
121 | # Parameters: @list - list of values to iterate over | ||||
122 | # Returns: Array (list) iterator | ||||
123 | # Exceptions: Iterator::X::Am_Now_Exhausted | ||||
124 | # Notes: Makes an internal copy of the list. | ||||
125 | sub ilist | ||||
126 | { | ||||
127 | my @items = @_; | ||||
128 | my $index=0; | ||||
129 | return Iterator->new( sub | ||||
130 | { | ||||
131 | Iterator::is_done if ($index >= @items); | ||||
132 | return $items[$index++]; | ||||
133 | }); | ||||
134 | } | ||||
135 | |||||
136 | # Function name: iarray | ||||
137 | # Synopsis: $iter = iarray ($a_ref); | ||||
138 | # Description: Creates an iterator from an array reference | ||||
139 | # Created: 07/28/2005 by EJR | ||||
140 | # Parameters: $a_ref - Reference to array to iterate over | ||||
141 | # Returns: Array iterator | ||||
142 | # Exceptions: Iterator::X::Parameter_Error | ||||
143 | # Iterator::X::Am_Now_Exhausted | ||||
144 | # Notes: Does not make an internal copy of the list. | ||||
145 | sub iarray ($) | ||||
146 | # spent 216µs (51+165) within Iterator::Util::iarray which was called 4 times, avg 54µs/call:
# 4 times (51µs+165µs) by Data::DPath::Context::_iter at line 410 of Data/DPath/Context.pm, avg 54µs/call | ||||
147 | 4 | 2µs | my $items = shift; | ||
148 | 4 | 1µs | my $index=0; | ||
149 | |||||
150 | 4 | 3µs | Iterator::X::Parameter_Error->throw-> | ||
151 | (q{Argument to iarray must be an array reference}) | ||||
152 | if ref $items ne 'ARRAY'; | ||||
153 | |||||
154 | return Iterator->new( sub | ||||
155 | # spent 2.32ms (40µs+2.28) within Iterator::Util::__ANON__[/home/ss5/perl5/perlbrew/perls/tapper-perl/lib/site_perl/5.16.3/Iterator/Util.pm:158] which was called 17 times, avg 137µs/call:
# 13 times (31µs+2.28ms) by Iterator::value at line 227 of Iterator.pm, avg 178µs/call
# 4 times (10µs+0s) by Iterator::_initialize at line 168 of Iterator.pm, avg 2µs/call | ||||
156 | 17 | 11µs | 4 | 2.28ms | Iterator::is_done if $index >= @$items; # spent 2.28ms making 4 calls to Iterator::is_done, avg 571µs/call |
157 | 13 | 47µs | return $items->[$index++]; | ||
158 | 4 | 42µs | 4 | 165µs | }); # spent 165µs making 4 calls to Iterator::new, avg 41µs/call |
159 | } | ||||
160 | |||||
161 | # Function name: ihead | ||||
162 | # Synopsis: $iter = ihead ($num, $some_other_iterator); | ||||
163 | # Synopsis: @valuse = ihead ($num, $iterator); | ||||
164 | # Description: Returns at most $num items from other iterator. | ||||
165 | # Created: 07/28/2005 by EJR | ||||
166 | # 08/02/2005 EJR: combined with ahead, per Will Coleda | ||||
167 | # Parameters: $num - Max number of items to return | ||||
168 | # $some_other_iterator - another iterator | ||||
169 | # Returns: limited iterator | ||||
170 | # Exceptions: Iterator::X::Parameter_Error | ||||
171 | # Iterator::X::Am_Now_Exhausted | ||||
172 | sub ihead | ||||
173 | { | ||||
174 | my $num = shift; | ||||
175 | my $iter = shift; | ||||
176 | |||||
177 | Iterator::X::Parameter_Error->throw | ||||
178 | (q{Second parameter for ihead must be an Iterator}) | ||||
179 | unless UNIVERSAL::isa($iter, 'Iterator'); | ||||
180 | |||||
181 | # List context? Return the first $num elements. | ||||
182 | if (wantarray) | ||||
183 | { | ||||
184 | my @a; | ||||
185 | while ($iter->isnt_exhausted && (!defined($num) || $num-- > 0)) | ||||
186 | { | ||||
187 | push @a, $iter->value; | ||||
188 | } | ||||
189 | return @a; | ||||
190 | } | ||||
191 | |||||
192 | # Scalar context: return an iterator to return at most $num elements. | ||||
193 | return Iterator->new(sub | ||||
194 | { | ||||
195 | Iterator::is_done if $num <= 0; | ||||
196 | |||||
197 | $num--; | ||||
198 | return $iter->value; | ||||
199 | }); | ||||
200 | } | ||||
201 | |||||
202 | # Function name: iappend | ||||
203 | # Synopsis: $iter = iappend (@iterators); | ||||
204 | # Description: Joins a bunch of iterators together. | ||||
205 | # Created: 07/28/2005 by EJR | ||||
206 | # Parameters: @iterators - any number of other iterators | ||||
207 | # Returns: A "merged" iterator. | ||||
208 | # Exceptions: Iterator::X::Parameter_Error | ||||
209 | # Iterator::X::Am_Now_Exhausted | ||||
210 | sub iappend | ||||
211 | { | ||||
212 | my @its = @_; | ||||
213 | |||||
214 | # Check types | ||||
215 | foreach (@its) | ||||
216 | { | ||||
217 | Iterator::X::Parameter_Error->throw | ||||
218 | (q{All parameters for iarray must be Iterators}) | ||||
219 | unless UNIVERSAL::isa($_, 'Iterator'); | ||||
220 | } | ||||
221 | |||||
222 | # Passthru, if there's only one. | ||||
223 | return $its[0] if @its == 1; | ||||
224 | |||||
225 | return Iterator->new (sub | ||||
226 | { | ||||
227 | my $val; | ||||
228 | |||||
229 | # Any empty iterators at front of list? Remove'em. | ||||
230 | while (@its && $its[0]->is_exhausted) | ||||
231 | { | ||||
232 | shift @its; | ||||
233 | } | ||||
234 | |||||
235 | # No more iterators? Then we're done. | ||||
236 | Iterator::is_done | ||||
237 | if @its == 0; | ||||
238 | |||||
239 | # Return the next value of the iterator at the head of the list. | ||||
240 | return $its[0]->value; | ||||
241 | }); | ||||
242 | } | ||||
243 | |||||
244 | # Function name: ipairwise | ||||
245 | # Synopsis: $iter = ipairwise {code} ($iter1, $iter2); | ||||
246 | # Description: Applies an operation to pairs of values from iterators. | ||||
247 | # Created: 07/28/2005 by EJR | ||||
248 | # Parameters: code - transformation, may use $a and $b | ||||
249 | # $iter1 - First iterator; "$a" value. | ||||
250 | # $iter2 - First iterator; "$b" value. | ||||
251 | # Returns: Iterator | ||||
252 | # Exceptions: Iterator::X::Parameter_Error | ||||
253 | # Iterator::X::Am_Now_Exhausted | ||||
254 | sub ipairwise (&$$) | ||||
255 | { | ||||
256 | my $op = shift; | ||||
257 | my $iterA = shift; | ||||
258 | my $iterB = shift; | ||||
259 | |||||
260 | # Check types | ||||
261 | for ($iterA, $iterB) | ||||
262 | { | ||||
263 | Iterator::X::Parameter_Error->throw | ||||
264 | (q{Second and third parameters for ipairwise must be Iterators}) | ||||
265 | unless UNIVERSAL::isa($_, 'Iterator'); | ||||
266 | } | ||||
267 | |||||
268 | return Iterator->new(sub | ||||
269 | { | ||||
270 | Iterator::is_done | ||||
271 | if $iterA->is_exhausted || $iterB->is_exhausted; | ||||
272 | |||||
273 | # Localize $a and $b | ||||
274 | # My thanks to Benjamin Goldberg for this little bit of evil. | ||||
275 | my ($caller_a, $caller_b) = do | ||||
276 | { | ||||
277 | my $pkg; | ||||
278 | my $i = 1; | ||||
279 | while (1) | ||||
280 | { | ||||
281 | $pkg = caller($i++); | ||||
282 | last if $pkg ne 'Iterator' && $pkg ne 'Iterator::Util'; | ||||
283 | } | ||||
284 | 2 | 196µs | 2 | 28µs | # spent 18µs (8+10) within Iterator::Util::BEGIN@284 which was called:
# once (8µs+10µs) by Data::DPath::Context::BEGIN@19 at line 284 # spent 18µs making 1 call to Iterator::Util::BEGIN@284
# spent 10µs making 1 call to strict::unimport |
285 | \*{$pkg.'::a'}, \*{$pkg.'::b'}; | ||||
286 | }; | ||||
287 | |||||
288 | # Set caller's $a and $b | ||||
289 | local (*$caller_a, *$caller_b) = \($iterA->value, $iterB->value); | ||||
290 | |||||
291 | # Invoke caller's operation | ||||
292 | return $op->(); | ||||
293 | }); | ||||
294 | } | ||||
295 | |||||
296 | # Function name: iskip | ||||
297 | # Synopsis: $iter = iskip $num, $another_iterator | ||||
298 | # Description: Skips the first $num values of another iterator | ||||
299 | # Created: 07/28/2005 by EJR | ||||
300 | # Parameters: $num - how many values to skip | ||||
301 | # $another_iterator - another iterator | ||||
302 | # Returns: Sequence iterator | ||||
303 | # Exceptions: None | ||||
304 | sub iskip | ||||
305 | { | ||||
306 | my $num = shift; | ||||
307 | my $it = shift; | ||||
308 | |||||
309 | Iterator::X::Parameter_Error->throw | ||||
310 | (q{Second parameter for iskip must be an Iterator}) | ||||
311 | unless UNIVERSAL::isa($it, 'Iterator'); | ||||
312 | |||||
313 | # Discard first $num values | ||||
314 | $it->value while $it->isnt_exhausted && $num-->0; | ||||
315 | |||||
316 | return $it; | ||||
317 | } | ||||
318 | |||||
319 | |||||
320 | # Function name: iskip_until | ||||
321 | # Synopsis: $iter = iskip_until {code}, $another_iterator | ||||
322 | # Description: Skips values of another iterator until {code} is true. | ||||
323 | # Created: 07/28/2005 by EJR | ||||
324 | # Parameters: {code} - Determines when to start returning values | ||||
325 | # $another_iterator - another iterator | ||||
326 | # Returns: Sequence iterator | ||||
327 | # Exceptions: Iterator::X::Am_Now_Exhausted | ||||
328 | sub iskip_until (&$) | ||||
329 | { | ||||
330 | my $code = shift; | ||||
331 | my $iter = shift; | ||||
332 | my $value; | ||||
333 | my $found_it = 0; | ||||
334 | |||||
335 | Iterator::X::Parameter_Error->throw | ||||
336 | (q{Second parameter for iskip_until must be an Iterator}) | ||||
337 | unless UNIVERSAL::isa($iter, 'Iterator'); | ||||
338 | |||||
339 | # Discard first $num values | ||||
340 | while ($iter->isnt_exhausted) | ||||
341 | { | ||||
342 | local $_ = $iter->value; | ||||
343 | if ($code->()) | ||||
344 | { | ||||
345 | $found_it = 1; | ||||
346 | $value = $_; | ||||
347 | last; | ||||
348 | } | ||||
349 | } | ||||
350 | |||||
351 | # Didn't find it? Pity. | ||||
352 | Iterator::is_done | ||||
353 | unless $found_it; | ||||
354 | |||||
355 | # Return an iterator with this value, and all remaining values. | ||||
356 | return iappend ilist($value), $iter; | ||||
357 | } | ||||
358 | |||||
359 | |||||
360 | # Function name: imesh / izip | ||||
361 | # Synopsis: $iter = imesh ($iter1, $iter2, ...) | ||||
362 | # Description: Merges other iterators together. | ||||
363 | # Created: 07/30/2005 by EJR | ||||
364 | # Parameters: Any number of other iterators. | ||||
365 | # Returns: Sequence iterator | ||||
366 | # Exceptions: Iterator::X::Parameter_Error | ||||
367 | # Iterator::X::Am_Now_Exhausted | ||||
368 | 1 | 700ns | foreach my $sub (qw/imesh izip/) | ||
369 | { | ||||
370 | 2 | 28µs | 2 | 26µs | # spent 18µs (9+9) within Iterator::Util::BEGIN@370 which was called:
# once (9µs+9µs) by Data::DPath::Context::BEGIN@19 at line 370 # spent 18µs making 1 call to Iterator::Util::BEGIN@370
# spent 9µs making 1 call to strict::unimport |
371 | *$sub = sub | ||||
372 | { | ||||
373 | 2 | 186µs | 2 | 24µs | # spent 16µs (7+9) within Iterator::Util::BEGIN@373 which was called:
# once (7µs+9µs) by Data::DPath::Context::BEGIN@19 at line 373 # spent 16µs making 1 call to Iterator::Util::BEGIN@373
# spent 9µs making 1 call to strict::import |
374 | |||||
375 | my @iterators = @_; | ||||
376 | my $it_index = 0; | ||||
377 | |||||
378 | foreach my $iter (@iterators) | ||||
379 | { | ||||
380 | Iterator::X::Parameter_Error->throw( | ||||
381 | "Argument to $sub is not an iterator") | ||||
382 | unless UNIVERSAL::isa($iter, 'Iterator'); | ||||
383 | } | ||||
384 | |||||
385 | return Iterator->new (sub | ||||
386 | { | ||||
387 | Iterator::is_done | ||||
388 | if $iterators[$it_index]->is_exhausted(); | ||||
389 | |||||
390 | my $retval = $iterators[$it_index]->value(); | ||||
391 | |||||
392 | if (++$it_index >= @iterators) | ||||
393 | { | ||||
394 | $it_index = 0; | ||||
395 | } | ||||
396 | |||||
397 | return $retval; | ||||
398 | }); | ||||
399 | 2 | 6µs | }; | ||
400 | } | ||||
401 | |||||
402 | # Function name: iuniq | ||||
403 | # Synopsis: $iter = iuniq ($another_iterator); | ||||
404 | # Description: Removes duplicate entries from an iterator. | ||||
405 | # Created: 07/30/2005 by EJR | ||||
406 | # Parameters: Another iterator. | ||||
407 | # Returns: Sequence iterator | ||||
408 | # Exceptions: Iterator::X::Parameter_Error | ||||
409 | # Iterator::X::Am_Now_Exhausted | ||||
410 | sub iuniq | ||||
411 | { | ||||
412 | Iterator::X::Parameter_Error->throw ("Too few parameters to iuniq") | ||||
413 | if @_ < 1; | ||||
414 | Iterator::X::Parameter_Error->throw ("Too many parameters to iuniq") | ||||
415 | if @_ > 1; | ||||
416 | |||||
417 | my $iter = shift; | ||||
418 | Iterator::X::Parameter_Error->throw("Argument to iuniq is not an iterator") | ||||
419 | unless UNIVERSAL::isa($iter, 'Iterator'); | ||||
420 | |||||
421 | my %did_see; | ||||
422 | return Iterator->new (sub | ||||
423 | { | ||||
424 | my $value; | ||||
425 | while (1) | ||||
426 | { | ||||
427 | Iterator::is_done | ||||
428 | if $iter->is_exhausted; | ||||
429 | |||||
430 | $value = $iter->value; | ||||
431 | last if !$did_see{$value}++; | ||||
432 | } | ||||
433 | return $value; | ||||
434 | }); | ||||
435 | } | ||||
436 | |||||
437 | 1 | 5µs | 1; | ||
438 | __END__ |