1Data::Tumbler(3) User Contributed Perl Documentation Data::Tumbler(3)
2
3
4
6 Data::Tumbler - Dynamic generation of nested combinations of variants
7
9 $tumbler = Data::Tumbler->new(
10
11 add_path => sub {
12 my ($path, $name) = @_;
13 return [ @$path, $name ];
14 },
15
16 add_context => sub {
17 my ($context, $value) = @_;
18 return [ @$context, $value ]
19 },
20
21 consumer => sub {
22 my ($path, $context, $payload) = @_;
23 print "@$path: @$context\n";
24 },
25 );
26
27 $tumbler->tumble(
28 [ # provider code refs
29 sub { (red => 42, green => 24, mauve => 19) },
30 sub { (circle => 1, square => 2) },
31 # ...
32 ],
33 [], # initial path
34 [], # initial context
35 [], # initial payload
36 );
37
38 The consumer code outputs:
39
40 green circle: 24 1
41 green square: 24 2
42 mauve circle: 19 1
43 mauve square: 19 2
44 red circle: 42 1
45 red square: 42 2
46
47 Here's a longer example showing more features:
48
49 use List::Util qw(sum);
50
51 $tumbler = Data::Tumbler->new(
52
53 # The default add_path is as shown above
54 # The default add_context is as shown above
55
56 consumer => sub {
57 my ($path, $context, $payload) = @_;
58 printf "path: %-20s context: %-12s payload: %s\n",
59 join("/", @$path),
60 join(", ", @$context),
61 join(", ", map { "$_=>$payload->{$_}" } sort keys %$payload);
62 },
63 );
64
65 $tumbler->tumble(
66 [ # providers
67 sub {
68 my ($path, $context, $payload) = @_;
69
70 my %variants = (red => 42, green => 24, mauve => 19);
71
72 return %variants;
73 },
74 sub {
75 my ($path, $context, $payload) = @_;
76
77 # change paint to matt based on context
78 $payload->{paint} = 'matt' if sum(@$context) > 20;
79
80 my %variants = (circle => 10, square => 20);
81
82 # add an extra triangular variant for mauve
83 $variants{triangle} = 13 if grep { $_ eq 'mauve' } @$path;
84
85 return %variants;
86 },
87 sub {
88 my ($path, $context, $payload) = @_;
89
90 # skip all variants if path contains anything red or circular
91 return if grep { $_ eq 'red' or $_ eq 'circle' } @$path;
92
93 $payload->{spotty} = 1 if sum(@$context) > 35;
94
95 my %variants = (small => 17, large => 92);
96
97 return %variants;
98 },
99 # ...
100 ],
101 [], # initial path
102 [], # initial context
103 { paint => 'gloss' }, # initial payload
104 );
105
106 The consumer code outputs:
107
108 path: green/square/large context: 24, 20, 92 payload: paint=>matt, spotty=>1
109 path: green/square/small context: 24, 20, 17 payload: paint=>matt, spotty=>1
110 path: mauve/square/large context: 19, 20, 92 payload: paint=>gloss, spotty=>1
111 path: mauve/square/small context: 19, 20, 17 payload: paint=>gloss, spotty=>1
112 path: mauve/triangle/large context: 19, 13, 92 payload: paint=>gloss
113 path: mauve/triangle/small context: 19, 13, 17 payload: paint=>gloss
114
116 NOTE: This is alpha code and liable to change while it and
117 Test::WriteVariants mature.
118
119 The tumble() method calls a sequence of 'provider' code references each
120 of which returns a hash. The first provider is called and then, for
121 each hash item it returns, the tumble() method recurses to call the
122 next provider.
123
124 The recursion continues until there are no more providers to call, at
125 which point the consumer code reference is called. Effectively the
126 providers create a tree of combinations and the consumer is called at
127 the leafs of the tree.
128
129 If a provider returns no items then that part of the tree is pruned.
130 Further providers, if any, are not called and the consumer is not
131 called.
132
133 During a call to tumble() three values are passed down through the tree
134 and into the consumer: path, context, and payload.
135
136 The path and context are derived from the names and values of the
137 hashes returned by the providers. Typically the path define the current
138 "path" through the tree of combinations.
139
140 The providers are passed the current path, context, and payload. The
141 payload is cloned at each level of recursion so that any changes made
142 to it by providers are only visible within the scope of the generated
143 sub-tree.
144
145 Note that although the example above shows the path, context and
146 payload as array references, the tumbler code makes no assumptions
147 about them. They can be any kinds of values.
148
149 See Test::WriteVariants for a practical example use.
150
152 consumer
153 $tumbler->consumer( sub { my ($path, $context, $payload) = @_; ... } );
154
155 Defines the code reference to call at the leafs of the generated tree
156 of combinations. The default is to throw an exception.
157
158 add_path
159 $tumbler->add_path( sub { my ($path, $name) = @_; return [ @$path, $name ] } )
160
161 Defines the code reference to call to create a new path value that
162 combines the existing path and the new name. The default is shown in
163 the example above.
164
165 add_context
166 $tumbler->add_context( sub { my ($context, $value) = @_; return [ @$context, $value ] } )
167
168 Defines the code reference to call to create a new context value that
169 combines the existing context and the new value. The default is shown
170 in the example above.
171
173 new
174 Contructs new Data::Tumbler, deals with initial values for
175 "ATTRIBUTES".
176
177 tumble
178 Tumbles providers to compute variants.
179
181 Please report any bugs or feature requests to "bug-Data-Tumbler at
182 rt.cpan.org", or through the web interface at
183 <http://rt.cpan.org/NoAuth/ReportBug.html?Queue=Data-Tumbler>. I will
184 be notified, and then you'll automatically be notified of progress on
185 your bug as I make changes.
186
188 You can find documentation for this module with the perldoc command.
189
190 perldoc Data::Tumbler
191
192 You can also look for information at:
193
194 · RT: CPAN's request tracker
195
196 <http://rt.cpan.org/NoAuth/Bugs.html?Dist=Data-Tumbler>
197
198 · AnnoCPAN: Annotated CPAN documentation
199
200 <http://annocpan.org/dist/Data-Tumbler>
201
202 · CPAN Ratings
203
204 <http://cpanratings.perl.org/d/Data-Tumbler>
205
206 · Search CPAN
207
208 <http://search.cpan.org/dist/Data-Tumbler/>
209
211 Tim Bunce, "<timb at cpan.org>"
212
214 This module has been created to support DBI::Test in design and
215 separation of concerns.
216
218 Copyright 2014-2015 Tim Bunce and Perl5 DBI Team.
219
221 This program is free software; you can redistribute it and/or modify it
222 under the terms of either:
223
224 a) the GNU General Public License as published by the Free
225 Software Foundation; either version 1, or (at your option) any
226 later version, or
227
228 b) the "Artistic License" which comes with this Kit.
229
230 This program is distributed in the hope that it will be useful, but
231 WITHOUT ANY WARRANTY; without even the implied warranty of
232 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See either the
233 GNU General Public License or the Artistic License for more details.
234
235
236
237perl v5.30.0 2019-07-26 Data::Tumbler(3)