File Coverage

blib/lib/NestedMap.pm
Criterion Covered Total %
statement 10 10 100.0
branch n/a
condition n/a
subroutine 3 3 100.0
pod 1 1 100.0
total 14 14 100.0


line stmt bran cond sub pod time code
1             package NestedMap;
2              
3             require Exporter;
4             @ISA = qw(Exporter);
5             @EXPORT = qw(nestedmap);
6              
7             $VERSION = '1.0';
8              
9 1     1   883 use strict;
  1         2  
  1         36  
10 1     1   5 use warnings;
  1         2  
  1         124  
11              
12             =head1 NAME
13              
14             NestedMap - a module to make nesting map{}s inside map{}s easier
15              
16             =head1 SYNOPSIS
17              
18             # show all combinations of (A,B,C) (a,b,c) and (1,2,3)
19             print join("\n",
20             nestedmap {
21             nestedmap {
22             nestedmap {
23             join('',@NestedMap::stack[0..2])
24             } qw(A B C)
25             } qw(a b c)
26             } qw(1 2 3)
27             );
28              
29             # a zip() function for any number of lists of varying length
30             sub zipn {
31             my @args = @_;
32             [
33             nestedmap {
34             nestedmap {
35             defined($args[$_][$NestedMap::stack[1]]) ?
36             $args[$_][$NestedMap::stack[1]] :
37             ''
38             } 0..$#args
39             } 0 .. max(map { $#{$_[$_]} } 0..$#args)
40             ]
41             }
42            
43             NB - older versions of perl may not like the code blocks I use in these
44             examples. You may have to use:
45              
46             nestedmap sub { ... }, @list;
47              
48             instead of
49              
50             nestedmap { ... } @list;
51              
52             See the test suite for examples of the above code modified to use that
53             syntax.
54              
55             =head1 DESCRIPTION
56              
57             Perl's map{} function is very useful, but ain't so great when you try to
58             put map{}s inside map{}s, as inner maps can have no idea what the outer
59             map{}s are doing. NestedMap solves that, by maintaining a stack of all
60             the nested map{}s' ideas of what $_ is. It's useful if you want to
61             iterate over lists of lists.
62              
63             It exports one function into your namespace ...
64              
65             =over 4
66              
67             =item nestedmap
68              
69             This function takes any number of arguments, the first of which must be
70             a coderef (ie, either a reference to a subroutine, or an anonymous
71             subroutine). That subroutine should take one argument. It will be
72             called once for each of the remaining arguments given to nestedmap().
73             The return value of nestedmap() is a list of all the return values of
74             the user-supplied subroutine Within your subroutine, $_ is available
75             just like in an ordinary map{}. There is also an array called
76             @NestedMap::stack which lets you get at the 'parent' nestedmaps' values
77             of $_. The first element (element 0) is your own $_, the second is the
78             parent's, the third is the grandparent's, and so on. Yes, you can change
79             them. That would be considered evil. And funny.
80              
81             =back
82              
83             =head1 HOW IT DIFFERS FROM map{}
84              
85             Because nestedmap() is a subroutine, as is the user-supplied function,
86             then unlike with map{} (which is a perl built-in) the value of @_ will not
87             remain the same inside a pile of nestedmap()s. If you want to refer to the
88             same @_ throughout, then you will need to assign @_ to another variable
89             first. See the zipn() example in the synopsis above.
90              
91             =head1 BUGS
92              
93             No bugs are known, but if you find any please let me know, and send a test
94             case.
95              
96             =head1 FEEDBACK
97              
98             I welcome feedback about my code, including constructive criticism. And,
99             while this is free software (both free-as-in-beer and free-as-in-speech) I
100             also welcome payment. In particular, your bug reports will get moved to
101             the front of the queue if you buy me something from my wishlist, which can
102             be found at L.
103              
104             =head1 AUTHOR
105              
106             David Cantrell EFE
107              
108             =head1 COPYRIGHT
109              
110             Copyright 2003 David Cantrell
111              
112             This module is free-as-in-speech software, and may be used, distributed,
113             and modified under the same terms as Perl itself.
114              
115             =cut
116              
117             sub nestedmap(&@) {
118 18     18 1 219 my $f = shift;
119 55         273 map {
120 18         26 local @NestedMap::stack = ($_, @NestedMap::stack);
121 55         109 $f->($_);
122             } @_
123             }