1Algorithm::Loops(3) User Contributed Perl Documentation Algorithm::Loops(3)
2
3
4
6 Algorithm::Loops - Looping constructs: NestedLoops, MapCar*, Filter,
7 and NextPermute*
8
10 use Algorithm::Loops qw(
11 Filter
12 MapCar MapCarU MapCarE MapCarMin
13 NextPermute NextPermuteNum
14 NestedLoops
15 );
16
17 my @copy= Filter {tr/A-Z'.,"()/a-z/d} @list;
18 my $string= Filter {s/\s*$/ /} @lines;
19
20 my @transposed= MapCarU {[@_]} @matrix;
21
22 my @list= sort getList();
23 do {
24 usePermutation( @list );
25 } while( NextPermute( @list ) );
26
27 my $len= @ARGV ? $ARGV[0] : 3;
28 my @list= NestedLoops(
29 [ ( [ 1..$len ] ) x $len ],
30 sub { "@_" },
31 );
32
33 If you want working sample code to try, see below in the section
34 specific to the function(s) you want to try. The above samples only
35 give a feel for how the functions are typically used.
36
38 Algorithm::Loops provides the functions listed below. By default, no
39 functions are exported into your namespace (package / symbol table) in
40 order to encourage you to list any functions that you use in the "use
41 Algorithm::Loops" statement so that whoever ends up maintaining your
42 code can figure out which module you got these functions from.
43
44 Filter
45 Similar to "map" but designed for use with s/// and other reflexive
46 operations. Returns a modified copy of a list.
47
48 MapCar, MapCarU, MapCarE, and MapCarMin
49 All similar to "map" but loop over multiple lists at the same time.
50
51 NextPermute and NextPermuteNum
52 Efficiently find all (unique) permutations of a list, even if it
53 contains duplicate values.
54
55 NestedLoops
56 Simulate "foreach" loops nested arbitrarily deep.
57
58 Filter(\&@)
59 Overview
60
61 Produces a modified copy of a list of values. Ideal for use with s///.
62 If you find yourself trying to use s/// or tr/// inside of map (or
63 grep), then you should probably use Filter instead.
64
65 For example:
66
67 use Algorithm::Loops qw( Filter );
68
69 @copy = Filter { s/\\(.)/$1/g } @list;
70 $text = Filter { s/^\s+// } @lines;
71
72 The same process can be accomplished using a careful and more complex
73 invocation of map, grep, or foreach. However, many incorrect ways to
74 attempt this seem rather seductively appropriate so this function helps
75 to discourage such (rather common) mistakes.
76
77 Usage
78
79 Filter has a prototype specification of (\&@).
80
81 This means that it demands that the first argument that you pass to it
82 be a CODE reference. After that you can pass a list of as many or as
83 few values as you like.
84
85 For each value in the passed-in list, a copy of the value is placed
86 into $_ and then your CODE reference is called. Your subroutine is
87 expected to modify $_ and this modified value is then placed into the
88 list of values to be returned by Filter.
89
90 If used in a scalar context, Filter returns a single string that is the
91 result of:
92
93 $string= join "", @results;
94
95 Note that no arguments are passed to your subroutine (so don't bother
96 with @_) and any value "return"ed by your subroutine is ignored.
97
98 Filter's prototype also means that you can use the "map BLOCK"-like
99 syntax by leaving off the "sub" keyword if you also leave off the comma
100 after the block that defines your anonymous subroutine:
101
102 my @copy= Filter sub {s/\s/_/g}, @list;
103 # becomes: v^^^ v ^
104 my @copy= Filter {s/\s/_/g} @list;
105
106 Most of our examples will use this shorter syntax.
107
108 Note also that by importing Filter via the "use" statement:
109
110 use Algorithm::Loops qw( Filter );
111
112 it gets declared before the rest of our code is compiled so we don't
113 have to use parentheses when calling it. We can if we want to,
114 however:
115
116 my @copy= Filter( sub {s/\s/_/g}, @list );
117
118 Note on "Function BLOCK LIST" bugs
119
120 Note that in at least some versions of Perl, support for the "Filter
121 BLOCK ..." syntax is somewhat fragile. For example:
122
123 ... Filter( {y/aeiou/UAEIO/} @list );
124
125 may give you this error:
126
127 Array found where operator expected
128
129 which can be fixed by dropping the parentheses:
130
131 ... Filter {y/aeiou/UAEIO/} @list;
132
133 So if you need or want to use parentheses when calling Filter, it is
134 best to also include the "sub" keyword and the comma:
135
136 # v <--------- These ---------> v
137 ... Filter( sub {y/aeiou/UAEIO/}, @list );
138 # require ^^^ <--- these ---> ^ (sometimes)
139
140 so your code will be portable to more versions of Perl.
141
142 Examples
143
144 Good code ignores "invisible" characters. So instead of just
145 chomp()ing, consider removing all trailing whitespace:
146
147 my @lines= Filter { s/\s+$// } <IN>;
148
149 or
150
151 my $line= Filter { s/\s+$// } scalar <IN>;
152
153 [ Note that Filter can be used in a scalar context but always puts its
154 arguments in a list context. So we need to use "scalar" or something
155 similar if we want to read only one line at a time from "IN" above. ]
156
157 Want to sort strings that contain mixtures of letters and natural
158 numbers (non-negative integers) both alphabetically and numerically at
159 the same time? This simple way to do a "natural" sort is also one of
160 the fastest. Great for sorting version numbers, file names, etc.:
161
162 my @sorted= Filter {
163 s#\d{2}(\d+)#\1#g
164 } sort Filter {
165 s#(\d+)# sprintf "%02d%s", length($1), $1 #g
166 } @data;
167
168 [ Note that at least some versions of Perl have a bug that breaks
169 "sort" if you write "sub {" as part of building the list of items to be
170 sorted but you don't provide a comparison routine. This bug means we
171 can't write the previous code as:
172
173 my @sorted= Filter {
174 s#\d{2}(\d+)#\1#g
175 } sort Filter sub {
176 s#(\d+)# sprintf "%02d%s", length($1), $1 #g
177 }, @data;
178
179 because it will produce the following error:
180
181 Undefined subroutine in sort
182
183 in some versions of Perl. Some versions of Perl may even require you
184 to write it like this:
185
186 my @sorted= Filter {
187 s#\d{2}(\d+)#\1#g
188 } sort &Filter( sub {
189 s#(\d+)# sprintf "%02d%s", length($1), $1 #g
190 }, @data );
191
192 Which is how I wrote it in ex/NaturalSort.plx. ]
193
194 Need to sort names? Then you'll probably want to ignore letter case
195 and certain punctuation marks while still preserving both:
196
197 my @compare= Filter {tr/A-Z'.,"()/a-z/d} @names;
198 my @indices= sort {$compare[$a] cmp $compare[$b]} 0..$#names;
199 @names= @names[@indices];
200
201 You can also roll your own simple HTML templating:
202
203 print Filter {
204 s/%(\w*)%/expand($1)/g
205 } $cgi->...,
206 ...
207 $cgi->...;
208
209 Note that it also also works correctly if you change how you output
210 your
211 HTML and accidentally switch from list to scalar context:
212
213 my $html= '';
214 ...
215 $html .= Filter {
216 s/%(\w*)%/expand($1)/g
217 } $cgi->...,
218 ...
219 $cgi->...;
220
221 Motivation
222
223 A reasonable use of map is:
224
225 @copy= map {lc} @list;
226
227 which sets @copy to be a copy of @list but with all of the elements
228 converted to lower case. But it is too easy to think that that could
229 also be done like this:
230
231 @copy= map {tr/A-Z/a-z/} @list; # Wrong
232
233 The reason why these aren't the same is similar to why we write:
234
235 $str= lc $str;
236
237 not
238
239 lc $str; # Useless use of 'lc' in void context
240
241 and we write:
242
243 $str =~ tr/A-Z/a-z/;
244
245 not
246
247 $new= ( $old =~ tr/A-Z/a-z/ ); # Wrong
248
249 That is, many things (such as lc) return a modified copy of what they
250 are given, but a few things (such as tr///, s///, chop, and chomp)
251 modify what they are given in-place.
252
253 This distinction is so common that we have several ways of switching
254 between the two forms. For example:
255
256 $two= $one + $other;
257 # vs.
258 $one += $other;
259
260 or
261
262 $two= substr($one,0,4);
263 # vs.
264 substr($one,4)= '';
265
266 I've even heard talk of adding some syntax to Perl to allow you to make
267 things like "lc" become reflexive, similar to how += is the reflexive
268 form of +.
269
270 But while many non-reflexive Perl operations have reflexive
271 counterparts, there are a few reflexive Perl operations that don't
272 really have non-reflexive counterparts: s///, tr///, chop, chomp.
273
274 You can write:
275
276 my $line= <STDIN>;
277 chomp( $line );
278 # or
279 chomp( my $line= <STDIN> );
280
281 but it somehow seems more natural to write:
282
283 my $line= chomp( <STDIN> ); # Wrong
284
285 So, if you dislike hiding the variable declaration inside of a function
286 call or dislike using two lines and repeating the variable name, then
287 you can now use:
288
289 my $line= Filter {chomp} ''.<STDIN>;
290
291 [ I used "''." to provide a scalar context so that only one line is
292 read from STDIN. ]
293
294 Or, for a better example, consider these valid alternatives:
295
296 my @lines= <STDIN>;
297 chomp( @lines );
298 # or
299 chomp( my @lines= <STDIN> );
300
301 And what you might expect to work (but doesn't):
302
303 my @lines= chomp( <STDIN> ); # Wrong
304
305 And what you can now use instead:
306
307 my @lines= Filter {chomp} <STDIN>;
308
309 Here are some examples of ways to use map/grep correctly to get
310 Filter's functionality:
311
312 Filter { CODE } @list
313 # vs
314 join "", map { local($_)= $_; CODE; $_ } @list
315 # vs
316 join "", grep { CODE; 1 } @{ [@list] }
317
318 Not horribly complex, but enough that it is very easy to forget part of
319 the solution, making for easy mistakes. I see mistakes related to this
320 quite frequently and have made such mistakes myself several times.
321
322 Some (including me) would even consider the last form above to be an
323 abuse (or misuse) of "grep".
324
325 You can also use "for"/"foreach" to get the same results as Filter:
326
327 my @copy= Filter { CODE } @list;
328 # vs
329 STATEMENT foreach my @copy= @list;
330 # or
331 my @copy= @list;
332 foreach( @copy ) {
333 CODE;
334 }
335
336 MapCar*
337 MapCar(\&@)
338 MapCarU(\&@)
339 MapCarE(\&@)
340 MapCarMin(\&@)
341
342 Usage
343
344 The MapCar* functions are all like "map" except they each loop over
345 more than one list at the same time.
346
347 [ The name "mapcar" comes from LISP. As I understand it, 'car' comes
348 from the acronym for a register of the processor where LISP was first
349 developed, one of two registers used to implement lists in LISP. I
350 only mention this so you won't waste too much time trying to figure out
351 what "mapcar" is supposed to mean. ]
352
353 The MapCar* functions all have prototype specifications of (\&@).
354
355 This means that they demand that the first argument that you pass be a
356 CODE reference. After that you should pass zero or more array
357 references.
358
359 Your subroutine is called (in a list context) and is passed the first
360 element of each of the arrays whose references you passed in (in the
361 corresponding order). Any value(s) returned by your subroutine are
362 pushed onto an array that will eventually be returned by MapCar*.
363
364 Next your subroutine is called and is passed the second element of each
365 of the arrays and any value(s) returned are pushed onto the results
366 array. Then the process is repeated with the third elements.
367
368 This continues until your subroutine has been passed all elements
369 [except for some cases with MapCarMin()]. If the longest array whose
370 reference you passed to MapCar() or MapCarU() contained $N elements,
371 then your subroutine would get called $N times.
372
373 Finally, the MapCar* function returns the accumulated list of values.
374 If called in a scalar context, the MapCar* function returns a reference
375 to an array containing these values.
376
377 [ I feel that having "map" return a count when called in a scalar
378 context is quite simply a mistake that was made when this feature was
379 copied from "grep" without properly considering the consequences.
380 Although it does make for the impressive and very impractical golf
381 solution of:
382
383 $sum=map{(1)x$_}@ints;
384
385 for adding up a list of natural numbers. q-: ]
386
387 Differences
388
389 The different MapCar* functions are only different in how they deal
390 with being pqssed arrays that are not all of the same size.
391
392 If not all of your arrays are the same length, then MapCarU() will pass
393 in "undef" for any values corresponding to arrays that didn't have
394 enough values. The "U" in "MapCarU" stands for "undef".
395
396 In contrast, MapCar() will simply leave out values for short arrays
397 (just like I left the "U" out of its name).
398
399 MapCarE() will croak without ever calling your subroutine unless all of
400 the arrays are the same length. It considers it an Error if your
401 arrays are not of Equal length and so throws an Exception.
402
403 Finally, MapCarMin() only calls your subroutine as many times as there
404 are elements in the shortest array.
405
406 In other words,
407
408 MapCarU \&MySub, [1,undef,3], [4,5], [6,7,8]
409
410 returns
411
412 ( MySub( 1, 4, 6 ),
413 MySub( undef, 5, 7 ),
414 MySub( 3, undef, 8 ),
415 )
416
417 While
418
419 MapCar \&MySub, [1,undef,3], [4,5], [6,7,8]
420
421 returns
422
423 ( MySub( 1, 4, 6 ),
424 MySub( undef, 5, 7 ),
425 MySub( 3, 8 ),
426 )
427
428 While
429
430 MapCarMin \&MySub, [1,undef,3], [4,5], [6,7,8]
431
432 returns
433
434 ( MySub( 1, 4, 6 ),
435 MySub( undef, 5, 7 ),
436 )
437
438 And
439
440 MapCarE \&MySub, [1,undef,3], [4,5], [6,7,8]
441
442 dies with
443
444 MapCarE: Arrays with different sizes (3 and 2)
445
446 Examples
447
448 Transposing a two-dimensional matrix:
449
450 my @transposed= MapCarE {[@_]} @matrix;
451
452 or, using references to the matrices and allowing for different row
453 lengths:
454
455 my $transposed= MapCarU {[@_]} @$matrix;
456
457 Formatting a date-time:
458
459 my $dateTime= join '', MapCarE {
460 sprintf "%02d%s", pop()+pop(), pop()
461 } [ (localtime)[5,4,3,2,1,0] ],
462 [ 1900, 1, (0)x4 ],
463 [ '// ::' =~ /./g, '' ];
464
465 Same thing but not worrying about warnings for using undefined values:
466
467 my $dateTime= join '', MapCarU {
468 sprintf "%02d%s", pop()+pop(), pop()
469 } [ (localtime)[5,4,3,2,1,0] ],
470 [ 1900, 1 ],
471 [ '// ::' =~ /./g ];
472
473 Combine with "map" to do matrix multiplication:
474
475 my @X= (
476 [ 1, 3 ],
477 [ 4, -1 ],
478 [ -2, 2 ],
479 );
480 my @Y= (
481 [ -6, 2, 5, -3 ],
482 [ 4, -1, 3, 1 ],
483 );
484 my @prod= map {
485 my $row= $_;
486 [
487 map {
488 my $sum= 0;
489 $sum += $_ for MapCarE {
490 pop() * pop();
491 } $row, $_;
492 $sum;
493 } MapCarE {\@_} @Y;
494 ]
495 } @X;
496
497 Report the top winners:
498
499 MapCarMin {
500 print pop(), " place goes to ", pop(), ".\n";
501 } [qw( First Second Third Fourth )],
502 \@winners;
503
504 Same thing (scalar context):
505
506 my $report= MapCarMin {
507 pop(), " place goes to ", pop(), ".\n";
508 } [qw( First Second Third Fourth )],
509 \@winners;
510
511 Displaying a duration:
512
513 my $ran= time() - $^T;
514 my $desc= join ', ', reverse MapCar {
515 my( $unit, $mult )= @_;
516 my $part= $ran;
517 if( $mult ) {
518 $part %= $mult;
519 $ran= int( $ran / $mult );
520 }
521 $unit .= 's' if 1 != $part;
522 $part ? "$part $unit" : ();
523 } [ qw( sec min hour day week year ) ],
524 [ 60, 60, 24, 7, 52 ];
525 $desc ||= '< 1 sec';
526 print "Script ran for $desc.\n";
527
528 NextPermute*
529 NextPermute(\@)
530 NextPermuteNum(\@)
531
532 Introduction
533
534 If you have a list of values, then a "permutation" of that list is the
535 same values but not (necessarily) in the same order.
536
537 NextPermute() and NextPermuteNum() each provide very efficient ways of
538 finding all of the (unique) permutations of a list (even if the list
539 contains duplicate values).
540
541 Usage
542
543 Each time you pass an array to a NextPermute* routine, the elements of
544 the array are shifted around to give you a new permutation. If the
545 elements of the array are in reverse-sorted order, then the array is
546 reversed (in-place, making it sorted) and a false value is returned.
547 Otherwise a true value is returned.
548
549 So, if you start out with a sorted array, then you can use that as your
550 first permutation and then call NextPermute* to get the next
551 permutation to use, until NextPermute* returns a false value (at which
552 point your array has been returned to its original, sorted order).
553
554 So you would use NextPermute() like this:
555
556 my @list= sort GetValuesSomehow();
557 do {
558 DoSomethingWithPermutation( @list );
559 } while( NextPermute( @list ) );
560
561 or, if your list only contains numbers, you could use NextPermuteNum()
562 like this:
563
564 my @list= sort {$a<=>$b} GetNumbersSomehow();
565 do {
566 DoSomethingWithPermutation( @list );
567 } while( NextPermuteNum( @list ) );
568
569 Notes
570
571 The NextPermute* functions each have a prototype specifications of
572 (\@). This means that they demand that you pass them a single array
573 which they will receive a reference to.
574
575 If you instead have a reference to an array, you'll need to use "@{ }"
576 when calling a NextPermute* routine:
577
578 } while( NextPermute( @{$av} ) );
579
580 (or use one of several other techniques which I will leave the
581 consideration of as an "exercise" for the more advanced readers of this
582 manual).
583
584 Note that this particular use of a function prototype is one that I am
585 not completely comfortable with. I am tempted to remove the prototype
586 and force you to create the reference yourself before/when calling
587 these functions:
588
589 } while( NextPermute( \@list ) ); # Wrong
590
591 because
592
593 · It makes it obvious to the reader of the code that a reference to
594 the array is what is being used by the routine. This makes the
595 reader more likely to realize/suspect that the array is being
596 modified in-place.
597
598 · Many/most uses of Perl function prototypes are more trouble than
599 they are worth. This makes using even the less problematic cases
600 often not a good idea.
601
602 However, I have decided to use a prototype here because:
603
604 · Several other functions from this module already use prototypes to
605 good advantage, enough advantage that I'd hate to lose it.
606
607 · Removing the prototype would require the addition of argument-
608 checking code that would get run each time a permutation is
609 computed, somewhat slowing down what is currently quite fast.
610
611 · The compile-time checking provided by the prototype can save
612 develop time over a run-time check by pointing out mistakes sooner.
613
614 Features
615
616 There are several features to NextPermute* that can be advantages over
617 other methods of finding permutations.
618
619 Iterators - No huge memory requirements
620 Some permutation generators return the full set of all permutations
621 (as a huge list of lists). Your input list doesn't have to be very
622 big at all for the resulting set to be too large to fit in your
623 available memory.
624
625 So the NextPermute* routines return each permutation, one at a
626 time, so you can process them all (eventually) without the need for
627 lots of memory.
628
629 A programming object that gives you access to things one-at-a-time
630 is called an "iterator".
631
632 No context - Hardly any memory required
633 The NextPermute* routines require no extra memory in the way of
634 context or lists to keep track of while constructing the
635 permutations.
636
637 Each call to a NextPermute* routine shuffles the items in the list
638 in-place, never making copies of more than a couple of values at a
639 time (when it swaps them).
640
641 [ This also means you don't have to bother with creating an object
642 to do the iterating. ]
643
644 Handles duplicate values
645 Unlike most permutation generators you are likely to find in Perl,
646 both NextPermute* routines correctly deal with lists containing
647 duplicate values.
648
649 The following example:
650
651 my @list= ( 3, 3, 3, 3 );
652 do {
653 print "@list\n";
654 } while( NextPermute( @list ) );
655
656 will only print the one line, "3 3 3 3\n", because NextPermute()
657 quickly determines that there are no other unique permutations.
658
659 Try out the demonstration program included in the "ex" subdirectory
660 of the source distribution of this module:
661
662 > perl ex/Permute.plx tool
663 1: loot
664 2: loto
665 3: ltoo
666 4: olot
667 5: olto
668 6: oolt
669 7: ootl
670 8: otlo
671 9: otol
672 10: tloo
673 11: tolo
674 12: tool
675
676 Most permutation generators would have listed each of those twice
677 (thinking that swapping an "o" with another "o" made a new
678 permutation). Or consider:
679
680 > perl ex/Permute.plx noon
681 1: nnoo
682 2: nono
683 3: noon
684 4: onno
685 5: onon
686 6: oonn
687
688 Most permutation generators would have listed each of those four
689 times.
690
691 Note that using a hash to eliminate duplicates would require a hash
692 table big enough to hold all of the (unique) permutations and so
693 would defeat the purpose of iterating. NextPermute* does not use a
694 hash to avoid duplicates.
695
696 Generated in sorted order
697 If you were to run code like:
698
699 my @list= sort GetValuesSomehow();
700 do {
701 print join('',@lista, $/);
702 } while( NextPermute( @list ) );
703
704 then the lines output would be sorted (assuming none of the values
705 in @list contained newlines. This may be convenient in some
706 corcumstances.
707
708 That is, the permutations are generated in sorted order. The first
709 permutations have the lowest values at the front of the list. As
710 you iterate, larger values are shifted to be in front of smaller
711 values, starting at the back of the list. So the value at the very
712 front of the list will change the fewest times (once for each
713 unique value in the list), while the value at the very end of the
714 list changes between most iterations.
715
716 Fast
717 If you don't have to deal with duplicate values, then
718 Algorithm::Permute provides some routines written in C (which makes
719 them harder to install but about twice as fast to run as the
720 NextPermute* routines) that you can use.
721
722 Algorithm::Permute also includes some fun benchmarks comparing
723 different Perl ways of finding permutations. I found NextPermute
724 to be faster than any of the routines included in those benchmarks
725 except for the ones written in C that I mentioned above. Though
726 none of the benchmarked routines deal with duplicates.
727
728 Notes
729
730 Note that NextPermute() considers two values (say $x and $y) to be
731 duplicates if (and only if) "$x eq $y".
732
733 NextPermuteNum() considers $x and $y to be duplicates if "$x == $y".
734
735 If you have a list of floating point numbers to permute, you might want
736 to use NextPermute() [instead of NextPermuteNum()] as it is easy to end
737 up with $x and $y that both display the same (say as "0.1") but are
738 just barely not equal numerically. Thus $x and $y would look equal and
739 it would be true that "$x eq $y" but also true that "$x != $y". So
740 NextPermute() would consider them to be duplicates but NextPermuteNum()
741 would not.
742
743 For example, $x could be slightly more than 1/10, likely about
744 0.1000000000000000056, while $y is slightly more at about
745 0.0999999999999999917 (both of which will be displayed as "0.1" by Perl
746 and be considered "eq" (on most platforms):
747
748 > perl -w -Mstrict
749 my $x= 0.1000000000000000056;
750 my $y= 0.0999999999999999917;
751 print "x=$x\ny=$y\n";
752 print "are eq\n" if $x eq $y;
753 print "are ==\n" if $x == $y;
754 print "are !=\n" if $x != $y;
755 <EOF>
756 x=0.1
757 y=0.1
758 are eq
759 are !=
760
761 NestedLoops
762 Introduction
763
764 Makes it easy to simulate loops nested to an arbitrary depth.
765
766 It is easy to write code like:
767
768 for my $a ( 0..$N ) {
769 for my $b ( $a+1..$N ) {
770 for my $c ( $b+1..$N ) {
771 Stuff( $a, $b, $c );
772 }
773 }
774 }
775
776 But what if you want the user to tell you how many loops to nest
777 together? The above code can be replaced with:
778
779 use Algorithm::Loops qw( NestedLoops );
780
781 my $depth= 3;
782 NestedLoops(
783 [ [ 0..$N ],
784 ( sub { [$_+1..$N] } ) x ($depth-1),
785 ],
786 \&Stuff,
787 );
788
789 Then you only have to change $depth to 4 to get the same results as:
790
791 for my $a ( 0..$N ) {
792 for my $b ( $a+1..$N ) {
793 for my $c ( $b+1..$N ) {
794 for my $d ( $c+1..$N ) {
795 Stuff( $a, $b, $c, $d );
796 }
797 }
798 }
799 }
800
801 Usage
802
803 The first argument to NestedLoops() is required and must be a reference
804 to an array. Each element of the array specifies the values for a
805 single loop to iterate over. The first element describes the outermost
806 loop. The last element describes the innermost loop.
807
808 If the next argument to NestedLoops is a hash reference, then it
809 specifies more advanced options. This argument can be omitted if you
810 don't need it.
811
812 If the last argument to NestedLoops is a code reference, then it will
813 be run inside the simulated loops. If you don't pass in this code
814 reference, then NestedLoops returns an iterator (described later) so
815 you can iterate without the restrictions of using a call-back.
816
817 So the possible ways to call NestedLoops are:
818
819 $iter= NestedLoops( \@Loops );
820 $iter= NestedLoops( \@Loops, \%Opts );
821 ... NestedLoops( \@Loops, \%Opts, \&Code );
822 ... NestedLoops( \@Loops, \&Code );
823
824 The "..."s above show that, when the final code reference is provided,
825 NestedLoops can return a few different types of information.
826
827 In a void context, NestedLoops simply iterates and calls the provided
828 code, discarding any values it returns. (Calling NestedLoops in a void
829 context without passing a final code reference is a fatal error.)
830
831 In a list context, NestedLoops "push"es the values returned by each
832 call to \&Code onto an array and then returns (copies of the values
833 from) that array.
834
835 In a scalar contetx, NestedLoops keeps a running total of the number of
836 values returned by each call to \&Code and then returns this total.
837 The value is the same as if you had called NestedLoops in a list
838 context and counted the number of values returned (except for using
839 less memory).
840
841 Note that \&Code is called in a list context no matter what context
842 NestedLoops was called in (in the current implementation).
843
844 In summary:
845
846 NestedLoops( \@loops, \%opts, \&code );
847 $count= NestedLoops( \@loops, \%opts, \&code );
848 @results= NestedLoops( \@loops, \%opts, \&code );
849
850 \@Loops
851
852 Each element of @Loops can be
853
854 an array refernce
855 which means the loop will iterate over the elements of that array,
856
857 a code refernce
858 to a subroutine that will return a reference to the array to loop
859 over.
860
861 You don't have to use a reference to a named array. You can, of
862 course, construct a reference to an anonymous array using "[...]", as
863 shown in most of the examples. You can also use any other type of
864 expression that rerurns an array reference.
865
866 \%Opts
867
868 If %Opts is passed in, then it should only zero or more of the
869 following keys. How NestedLoops interprets the values associated with
870 each key are described below.
871
872 OnlyWhen => $Boolean
873 OnlyWhen => \&Test
874 Value must either be a Boolean value or a reference to a subroutine
875 that will return a Boolean value.
876
877 Specifying a true value is the same as specifying a routine that
878 always returns a true value. Specifying a false value gives you
879 the default behavior (as if you did not include the OnlyWhen key at
880 all).
881
882 If it is a code reference, then it is called each time a new item
883 is selected by any of the loops. The list of selected items is
884 passed in.
885
886 The Boolean value returned says whether to use the list of selected
887 values. That is, a true value causes either \&Code to be called
888 (if specified) or the list to be returned by the iterator (if
889 \&Code was not specified).
890
891 If this key does not exist (or is specified with a false value),
892 then a default subroutine is used, like:
893
894 sub { return @_ == @Loops }
895
896 That is, only complete lists are used (by default). So:
897
898 my @list= NestedLoops(
899 [ ( [ 1..3 ] ) x 3 ],
900 { OnlyWhen => 0 },
901 sub { "@_" },
902 );
903
904 is similar to:
905
906 my @list= qw/ 111 112 113 121 122 123 131 132 133 211 212 ... /;
907
908 while
909
910 my @list= NestedLoops(
911 [ ( [ 1..3 ] ) x 3 ],
912 { OnlyWhen => 1 },
913 sub { "@_" },
914 );
915
916 is similar to:
917
918 my @list= qw/ 1 11 111 112 113 12 121 122 123
919 13 131 132 133 2 21 211 212 ... /;
920
921 Another example:
922
923 NestedLoops(
924 [ ( [ 1..3 ] ) x 3 ],
925 { OnlyWhen => 1 },
926 \&Stuff,
927 );
928
929 is similar to:
930
931 for my $a ( 1..3 ) {
932 Stuff( $a );
933 for my $b ( 1..3 ) {
934 Stuff( $a, $b );
935 for my $c ( 1..3 ) {
936 Stuff( $a, $b, $c );
937 }
938 }
939 }
940
941 Last example:
942
943 NestedLoops(
944 [ ( [ 1..3 ] ) x 3 ],
945 { OnlyWhen => \&Test },
946 \&Stuff,
947 );
948
949 is similar to:
950
951 for my $a ( 1..3 ) {
952 Stuff( $a ) if Test( $a );
953 for my $b ( 1..3 ) {
954 Stuff( $a, $b ) if Test( $a, $b );
955 for my $c ( 1..3 ) {
956 Stuff( $a, $b, $c )
957 if Test( $a, $b, $c );
958 }
959 }
960 }
961
962 \&Code
963
964 The subroutine that gets called for each iteration.
965
966 Iterator
967
968 If you don't pass in a final code reference to NestedLoops, then
969 NestedLoops will return an iterator to you (without having performed
970 any iterations yet).
971
972 The iterator is a code reference. Each time you call it, it returns
973 the next list of selected values. Any arguments you pass in are
974 ignored (at least in this release).
975
976 Examples
977
978 Finding non-repeating sequences of digits.
979
980 One way would be to loop over all digit combinations but only selecting
981 ones without repeats:
982
983 use Algorithm::Loops qw/ NestedLoops /;
984 $|= 1;
985 my $len= 3;
986 my $verbose= 1;
987 my $count= NestedLoops(
988 [ ( [0..9] ) x $len ],
989 { OnlyWhen => sub {
990 $len == @_
991 && join('',@_) !~ /(.).*?\1/;
992 #or && @_ == keys %{{@_,reverse@_}};
993 }
994 },
995 sub {
996 print "@_\n" if $verbose;
997 return 1;
998 },
999 );
1000 print "$count non-repeating $len-digit sequences.\n";
1001
1002 0 1 2
1003 0 1 3
1004 0 1 4
1005 0 1 5
1006 0 1 6
1007 0 1 7
1008 0 1 8
1009 0 1 9
1010 0 2 1
1011 ...
1012 9 8 5
1013 9 8 6
1014 9 8 7
1015 720 non-repeating 3-digit sequences.
1016
1017 But it would be nice to not waste time looping over, for example
1018 (2,1,2,0,0) through (2,1,2,9,9). That is, don't even pick 2 as the
1019 third value if we already picked 2 as the first.
1020
1021 A clever way to do that is to only iterate over lists where the digits
1022 increase from left to right. That will give us all sets of non-
1023 repeating digits and then we find all permutations of each:
1024
1025 use Algorithm::Loops qw/ NestedLoops NextPermute /;
1026 $|= 1;
1027 my $len= 3;
1028 my $verbose= 1;
1029 my $iter= NestedLoops(
1030 [ [0..9],
1031 ( sub { [$_+1..9] } ) x ($len-1),
1032 ],
1033 );
1034 my $count= 0;
1035 my @list;
1036 while( @list= $iter->() ) {
1037 do {
1038 ++$count;
1039 print "@list\n" if $verbose;
1040 } while( NextPermute(@list) );
1041 }
1042 print "$count non-repeating $len-digit sequences.\n";
1043
1044 0 1 2
1045 0 2 1
1046 1 0 2
1047 1 2 0
1048 2 0 1
1049 2 1 0
1050 0 1 3
1051 0 3 1
1052 1 0 3
1053 1 3 0
1054 3 0 1
1055 3 1 0
1056 0 1 4
1057 0 4 1
1058 ...
1059 9 6 8
1060 9 8 6
1061 7 8 9
1062 7 9 8
1063 8 7 9
1064 8 9 7
1065 9 7 8
1066 9 8 7
1067 720 non-repeating 3-digit sequences.
1068
1069 A third way is to construct the list of values to loop over by
1070 excluding values already selected:
1071
1072 use Algorithm::Loops qw/ NestedLoops /;
1073 $|= 1;
1074 my $len= 3;
1075 my $verbose= 1;
1076 my $count= NestedLoops(
1077 [ [0..9],
1078 ( sub {
1079 my %used;
1080 @used{@_}= (1) x @_;
1081 return [ grep !$used{$_}, 0..9 ];
1082 } ) x ($len-1),
1083 ],
1084 sub {
1085 print "@_\n" if $verbose;
1086 return 1;
1087 },
1088 );
1089 print "$count non-repeating $len-digit sequences.\n";
1090
1091 0 1 2
1092 0 1 3
1093 0 1 4
1094 0 1 5
1095 0 1 6
1096 0 1 7
1097 0 1 8
1098 0 1 9
1099 0 2 1
1100 0 2 3
1101 ...
1102 9 7 8
1103 9 8 0
1104 9 8 1
1105 9 8 2
1106 9 8 3
1107 9 8 4
1108 9 8 5
1109 9 8 6
1110 9 8 7
1111 720 non-repeating 3-digit sequences.
1112
1113 Future releases of this module may add features to makes these last two
1114 methods easier to write.
1115
1117 Hey! The above document had some coding errors, which are explained
1118 below:
1119
1120 Around line 955:
1121 '=item' outside of any '=over'
1122
1123
1124
1125perl v5.30.1 2020-01-29 Algorithm::Loops(3)