Data-Rmap
view release on metacpan or search on metacpan
lib/Data/Rmap.pm view on Meta::CPAN
use Lingua::EN::Numbers::Easy;
$words = [ 1, \2, { key => 3 } ];
$nums = dclone $words;
rmap { $_ = $N{$_} || $_ } $nums;
# Make an assertion about a structure
use Data::Dump;
rmap_ref {
blessed($_) && $_->isa('Question') && defined($_->name)
or die "Question doesn't have a name:", dump($_);
} @pages;
# Traverse a tree using localize state
$tree = [
one =>
two =>
[
three_one =>
three_two =>
[
three_three_one =>
],
three_four =>
],
four =>
[
[
five_one_one =>
],
],
];
@path = ('q');
rmap_to {
if(ref $_) {
local(@path) = (@path, 1); # ARRAY adds a new level to the path
$_[0]->recurse(); # does stuff within local(@path)'s scope
} else {
print join('.', @path), " = $_ \n"; # show the scalar's path
}
$path[-1]++; # bump last element (even when it was an aref)
} ARRAY|VALUE, $tree;
# OUTPUT
# q.1 = one
# q.2 = two
# q.3.1 = three_one
# q.3.2 = three_two
# q.3.3.1 = three_three_one
# q.3.4 = three_four
# q.4 = four
# q.5.1.1 = five_one_one
# replace CODE with "<CODE>"
$ perl -MData::Rmap=:all -E 'say join ":", rmap_code { "<CODE>" } sub{},sub{}'
<CODE>:<CODE>
# look inside code refs with PadWalker
$ perl -MData::Rmap=:all -MSub::Identify=:all -MPadWalker=:all -MSub::Name
use 5.10.0;
my $s = sub {}; sub A::a { $s };
say join ", ",
rmap_code {
sub_fullname($_), # name string
map { $_[0]->recurse } closed_over($_) # then recurse the sub innards
} \*A::a, subname b => sub { $s };
# A::a, main::__ANON__, main::b
=head1 Troubleshooting
Beware comma after block:
rmap { print }, 1..3;
^-------- bad news, you get an empty list:
rmap(sub { print $_; }), 1..3;
If you don't import a function, perl's confusion may produce:
$ perl -MData::Rmap -le 'rmap_scalar { print } 1'
Can't call method "rmap_scalar" without a package or object reference...
$ perl -MData::Rmap -le 'rmap_scalar { $_++ } 1'
Can't call method "rmap_scalar" without a package or object reference...
If there's two paths to an element, both will need to be cut.
If there's two paths to an element, one will be taken randomly when
there is an intervening hash.
Autovivification can lead to "Deep recursion" warnings if you test
C<< exists $_->{this}{that} >> instead of
C<< exists $_->{this} && exists $_->{this}{that} >>
as you may follow a long chain of "this"s
Alternatively use the "no autovivification" pragma to avoid this problem.
=head1 TODO
put for @_ in wrapper to allow parameters in a different wrapper,
solve localizing problem.
Store custom localized data about the traversal.
Seems too difficult and ugly when compare to doing it at the call site.
Should support multiple reentrancy so avoid the symbol table.
C<rmap_args { } $data_structure, @args> form to pass parameters.
Could potentially help localizing needs. (Maybe only recurse last item)
Benchmark. Use array based object and/or direct access internally.
Think about permitting different callback for different types.
The prototype syntax is a bit too flaky....
Ensure that no memory leaks are possible, leaking the closure.
=head1 SEE ALSO
map, grep, L<Storable>'s dclone, L<Scalar::Util>'s reftype and blessed
Faint traces of treemap:
( run in 0.974 second using v1.01-cache-2.11-cpan-39bf76dae61 )