Data::Tumbler(3)
π¦ Data::Tumbler β like, dynamic generation of nested combinations of variants, bestie
So this is Data::Tumbler(3), straight out of the User Contributed Perl Documentation section, and honestly? It's giving "tree of possibilities" main character energy. Let's get into it β¨
β¨ SYNOPSIS β¨
Okay so the whole vibe in one snippet:
$tumbler = Data::Tumbler->new(
add_path => sub {
my ($path, $name) = @_;
return [ @$path, $name ];
},
add_context => sub {
my ($context, $value) = @_;
return [ @$context, $value ]
},
consumer => sub {
my ($path, $context, $payload) = @_;
print "@$path: @$context\n";
},
);
$tumbler->tumble(
[ # provider code refs
sub { (red => 42, green => 24, mauve => 19) },
sub { (circle => 1, square => 2) },
# ...
],
[], # initial path
[], # initial context
[], # initial payload
);
And then the consumer prints this, no cap:
green circle: 24 1
green square: 24 2
mauve circle: 19 1
mauve square: 19 2
red circle: 42 1
red square: 42 2
Here's a longer example (List::Util qw(sum) era, so you know we're serious) showing more features π₯
use List::Util qw(sum);
$tumbler = Data::Tumbler->new(
# The default add_path is as shown above
# The default add_context is as shown above
consumer => sub {
my ($path, $context, $payload) = @_;
printf "path: %-20s context: %-12s payload: %s\n",
join("/", @$path),
join(", ", @$context),
join(", ", map { "$_=>$payload->{$_}" } sort keys %$payload);
},
);
$tumbler->tumble(
[ # providers
sub {
my ($path, $context, $payload) = @_;
my %variants = (red => 42, green => 24, mauve => 19);
return %variants;
},
sub {
my ($path, $context, $payload) = @_;
# change paint to matt based on context
$payload->{paint} = 'matt' if sum(@$context) > 20;
my %variants = (circle => 10, square => 20);
# add an extra triangular variant for mauve
$variants{triangle} = 13 if grep { $_ eq 'mauve' } @$path;
return %variants;
},
sub {
my ($path, $context, $payload) = @_;
# skip all variants if path contains anything red or circular
return if grep { $_ eq 'red' or $_ eq 'circle' } @$path;
$payload->{spotty} = 1 if sum(@$context) > 35;
my %variants = (small => 17, large => 92);
return %variants;
},
# ...
],
[], # initial path
[], # initial context
{ paint => 'gloss' }, # initial payload
);
So the consumer code outputs:
path: green/square/large context: 24, 20, 92 payload: paint=>matt, spotty=>1
path: green/square/small context: 24, 20, 17 payload: paint=>matt, spotty=>1
path: mauve/square/large context: 19, 20, 92 payload: paint=>gloss, spotty=>1
path: mauve/square/small context: 19, 20, 17 payload: paint=>gloss, spotty=>1
path: mauve/triangle/large context: 19, 13, 92 payload: paint=>gloss
path: mauve/triangle/small context: 19, 13, 17 payload: paint=>gloss
π DESCRIPTION π
NOTE: This is alpha code and liable to change while it and Test::WriteVariants mature. So like, don't build your whole personality on it yet π«Ά
The tumble() method calls a sequence of 'provider' code references, each of which returns a hash. The first provider is called and then, for each hash item it returns, the tumble() method recurses to call the next provider. It's a whole relay race, honestly πββοΈ
The recursion continues until there are no more providers to call, at which point the consumer code reference is called. Effectively the providers create a tree of combinations and the consumer is called at the leafs of the tree. π³
If a provider returns no items then that part of the tree is pruned. Further providers, if any, are not called and the consumer is not called. Bye, that branch, we hardly knew you π
During a call to tumble() three values are passed down through the tree and into the consumer: path, context, and payload.
The path and context are derived from the names and values of the hashes returned by the providers. Typically the path define the current "path" through the tree of combinations.
The providers are passed the current path, context, and payload. The payload is cloned at each level of recursion so that any changes made to it by providers are only visible within the scope of the generated sub-tree. Lowkey genius behaviour, every subtree gets its own little pocket dimension π§
Note that although the example above shows the path, context and payload as array references, the tumbler code makes no assumptions about them. They can be any kinds of values. Fr fr β anything. π
See Test::WriteVariants for a practical example use.
πΈ ATTRIBUTES πΈ
consumer
$tumbler->consumer( sub { my ($path, $context, $payload) = @_; ... } );
Defines the code reference to call at the leafs of the generated tree of combinations. The default is to throw an exception β so like, if you forget to set one, it will yell at you π
add_path
$tumbler->add_path( sub { my ($path, $name) = @_; return [ @$path, $name ] } )
Defines the code reference to call to create a new path value that combines the existing path and the new name. The default is shown in the example above.
add_context
$tumbler->add_context( sub { my ($context, $value) = @_; return [ @$context, $value ] } )
Defines the code reference to call to create a new context value that combines the existing context and the new value. The default is shown in the example above.
π METHODS π
new
Contructs new Data::Tumbler, deals with initial values for "ATTRIBUTES". (Yes, that's spelled "Contructs" in the source β iconic typo, we keep it π
)
tumble
Tumbles providers to compute variants. That's it. That's the whole description. Short king π
π BUGS π
Please report any bugs or feature requests to bug-Data-Tumbler at rt.cpan.org, or through the web interface at <http://rt.cpan.org/NoAuth/ReportBug.html?Queue=Data-Tumbler>. I will be notified, and then you'll automatically be notified of progress on your bug as I make changes. Look at that communication pipeline, we love to see it π«Ά
π SUPPORT π
You can find documentation for this module with the perldoc command.
perldoc Data::Tumbler
You can also look for information at:
- RT: CPAN's request tracker
<http://rt.cpan.org/NoAuth/Bugs.html?Dist=Data-Tumbler>
- AnnoCPAN: Annotated CPAN documentation
<http://annocpan.org/dist/Data-Tumbler>
- CPAN Ratings
<http://cpanratings.perl.org/d/Data-Tumbler>
- Search CPAN
<http://search.cpan.org/dist/Data-Tumbler/>
π AUTHOR π
Tim Bunce, <timb at cpan.org>
π ACKNOWLEDGEMENTS π
This module has been created to support DBI::Test in design and separation of concerns. Separation of concerns is such a slay concept, honestly.
β COPYRIGHT β
Copyright 2014-2015 Tim Bunce and Perl5 DBI Team.
π LICENSE π
This program is free software; you can redistribute it and/or modify it under the terms of either:
- the GNU General Public License as published by the Free Software Foundation; either version 1, or (at your option) any later version, or
- the "Artistic License" which comes with this Kit.
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See either the GNU General Public License or the Artistic License for more details.
Bestie, that ALL-CAPS warranty disclaimer is not a vibe, but it is legally required, so we keep it exactly as is π
And that's the whole page, babes π
β¨ This masterpiece is perl v5.42.0, dated 2018-10-09, and it's the Data::Tumbler(3) page β go tumble some providers, you've got this π¦π
π¦ where this page comes from
- opensuse-leap 16.0: perl-Data-Tumbler 0.010-bp160.1.11 Β· Artistic-1.0 OR GPL-1.0-or-later
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash-1017 on : a language model's rewrite of the original, under its terms