File Coverage

blib/lib/Sub/Data/Recursive.pm
Criterion Covered Total %
statement 54 66 81.8
branch 18 28 64.2
condition 0 6 0.0
subroutine 7 7 100.0
pod 2 2 100.0
total 81 109 74.3


line stmt bran cond sub pod time code
1             package Sub::Data::Recursive;
2 4     4   278505 use strict;
  4         39  
  4         129  
3 4     4   21 use warnings FATAL => 'all';
  4         8  
  4         222  
4              
5             our $VERSION = '0.02';
6              
7 4     4   22 use Scalar::Util qw/refaddr/;
  4         8  
  4         2748  
8              
9             sub invoke {
10 6     6 1 3343 my ($class, $code, @args) = @_;
11 6         22 _apply($code, +{}, @args);
12             }
13              
14             sub _apply {
15 20     20   35 my $code = shift;
16 20         29 my $seen = shift;
17              
18 20         25 my @retval;
19 20         36 for my $arg (@_) {
20 43 100       161 if(my $ref = ref $arg){
21 14         31 my $refaddr = refaddr($arg);
22 14         22 my $proto;
23              
24 14 50 0     51 if(defined($proto = $seen->{$refaddr})){
    100          
    50          
    0          
25             # noop
26             }
27             elsif($ref eq 'ARRAY'){
28 3         8 $proto = $seen->{$refaddr} = [];
29 3         5 @{$proto} = _apply($code, $seen, @{$arg});
  3         6  
  3         24  
30             }
31             elsif($ref eq 'HASH'){
32 11         25 $proto = $seen->{$refaddr} = {};
33 11         18 %{$proto} = _apply($code, $seen, %{$arg});
  11         25  
  11         38  
34             }
35             elsif($ref eq 'REF' or $ref eq 'SCALAR'){
36 0         0 $proto = $seen->{$refaddr} = \do{ my $scalar };
  0         0  
37 0         0 ${$proto} = _apply($code, $seen, ${$arg});
  0         0  
  0         0  
38             }
39             else{ # CODE, GLOB, IO, LVALUE etc.
40 0         0 $proto = $seen->{$refaddr} = $arg;
41             }
42              
43 14         33 push @retval, $proto;
44             }
45             else{
46 29 50       64 push @retval, defined($arg) ? $code->($arg) : $arg;
47             }
48             }
49              
50 20 100       79 return wantarray ? @retval : $retval[0];
51             }
52              
53             sub massive_invoke {
54 2     2 1 667 my ($class, $code, @args) = @_;
55 2         7 _massive_apply($code, +{}, undef, undef, @args);
56             }
57              
58             sub _massive_apply {
59 4     4   7 my $code = shift;
60 4         5 my $seen = shift;
61 4         7 my $context = shift;
62 4         6 my $keys = shift;
63              
64 4         6 my @retval;
65 4         9 for my $arg (@_) {
66 6 100       2969 if(my $ref = ref $arg){
67 2         6 my $refaddr = refaddr($arg);
68 2         3 my $proto;
69              
70 2 50 0     12 if(defined($proto = $seen->{$refaddr})){
    100          
    50          
    0          
71             # noop
72             }
73             elsif($ref eq 'ARRAY'){
74 1         4 $proto = $seen->{$refaddr} = [];
75 1         3 @{$proto} = _massive_apply($code, $seen, $ref, undef, @{$arg});
  1         4  
  1         6  
76             }
77             elsif($ref eq 'HASH'){
78 1         3 $proto = $seen->{$refaddr} = {};
79 1         2 %{$proto} = _massive_apply($code, $seen, $ref, [keys %{$arg}], %{$arg});
  1         3  
  1         4  
  1         6  
80             }
81             elsif($ref eq 'REF' or $ref eq 'SCALAR'){
82 0         0 $proto = $seen->{$refaddr} = \do{ my $scalar };
  0         0  
83 0         0 ${$proto} = _massive_apply($code, $seen, $ref, undef, ${$arg});
  0         0  
  0         0  
84             }
85             else{ # CODE, GLOB, IO, LVALUE etc.
86 0         0 $proto = $seen->{$refaddr} = $arg;
87             }
88              
89 2         7 push @retval, $proto;
90             }
91             else{
92 4 50       14 push @retval, defined($arg) ? $code->($arg, $context, $keys) : $arg;
93             }
94             }
95              
96 4 100       2496 return wantarray ? @retval : $retval[0];
97             }
98              
99             1;
100              
101             __END__