File Coverage

blib/lib/Tie/Reduce.pm
Criterion Covered Total %
statement 40 60 66.6
branch 3 6 50.0
condition n/a
subroutine 11 16 68.7
pod 5 5 100.0
total 59 87 67.8


line stmt bran cond sub pod time code
1 1     1   50484 use 5.006001;
  1         2  
2 1     1   4 use strict;
  1         2  
  1         14  
3 1     1   4 use warnings;
  1         1  
  1         186  
4              
5             package Tie::Reduce;
6              
7             our $AUTHORITY = 'cpan:TOBYINK';
8             our $VERSION = '0.003';
9              
10             ## suppresses warnings
11              
12             sub import {
13 1     1   4 my $class = shift;
14 1         2 my $caller = caller;
15 1         46 eval "package $caller; our (\$a, \$b)";
16             }
17              
18             ## tie interface
19              
20             sub TIESCALAR {
21 1     1   67 my $class = shift;
22 1         5 $class->new(@_);
23             }
24              
25             sub FETCH {
26 1 50   1   38 ref($_[0]) ne __PACKAGE__
27             ? $_[0]->get_value
28             : $_[0][0]; # shortcut if not subclassed
29             }
30              
31             sub STORE {
32             # if subclassed
33 4 50   4   23 if (ref($_[0]) ne __PACKAGE__) {
34             # take non-optimal route
35 0         0 my $av = $_[0]->can('assign_value');
36 0         0 goto $av; # preserve caller
37             }
38            
39 4         5 my ($self) = shift;
40 4         5 my ($new_value) = @_;
41 4         7 my ($old_value, $coderef) = @$self;
42              
43 4         5 my ($caller_a, $caller_b) = do {
44 4         5 my $pkg = caller();
45 1     1   6 no strict 'refs';
  1         2  
  1         112  
46 4         4 \*{$pkg . '::a'}, \*{$pkg . '::b'};
  4         8  
  4         6  
47             };
48 4         10 local (*$caller_a, *$caller_b);
49            
50 4         4 *$caller_a = \$old_value;
51 4         4 *$caller_b = \$new_value;
52            
53 4         7 $self->[0] = $coderef->($old_value, $new_value);
54             }
55              
56             ## OO interface
57              
58             sub new {
59 1     1 1 2 my $class = shift;
60 1         2 my ($coderef, $initial_value) = @_;
61 1     1   5 no warnings 'uninitialized';
  1         1  
  1         181  
62 1 50       4 if (ref($coderef) ne 'CODE') {
63 0         0 require Carp;
64 0         0 Carp::croak("Expected coderef; got $coderef");
65             }
66 1         3 bless [$initial_value, $coderef] => $class;
67             }
68              
69             sub get_value {
70 0     0 1   $_[0][0];
71             }
72              
73             sub set_value {
74 0     0 1   $_[0][0] = $_[1];
75             }
76              
77             sub assign_value {
78 0     0 1   my ($self) = shift;
79 0           my ($new_value) = @_;
80 0           my $old_value = $self->get_value;
81              
82 0           my ($caller_a, $caller_b) = do {
83 0           my $pkg = caller();
84 1     1   6 no strict 'refs';
  1         2  
  1         114  
85 0           \*{$pkg . '::a'}, \*{$pkg . '::b'};
  0            
  0            
86             };
87 0           local (*$caller_a, *$caller_b);
88            
89 0           *$caller_a = \$old_value;
90 0           *$caller_b = \$new_value;
91            
92 0           $self->set_value( $self->get_coderef->($old_value, $new_value) );
93             }
94              
95             sub get_coderef {
96 0     0 1   $_[0][1];
97             }
98              
99             sub _set_coderef {
100 0     0     $_[0][1] = $_[1];
101             }
102              
103             1;
104              
105             __END__