File Coverage

blib/lib/Statistics/R/REXP/Closure.pm
Criterion Covered Total %
statement 43 44 97.7
branch 21 24 87.5
condition 12 21 57.1
subroutine 10 10 100.0
pod 1 3 33.3
total 87 102 85.2


line stmt bran cond sub pod time code
1             package Statistics::R::REXP::Closure;
2             # ABSTRACT: an R closure
3             $Statistics::R::REXP::Closure::VERSION = '1.0';
4 12     12   20738 use 5.010;
  12         24  
5              
6 12     12   42 use Scalar::Util qw(refaddr blessed);
  12         13  
  12         534  
7              
8 12     12   517 use Class::Tiny::Antlers qw(-default around);
  12         4517  
  12         55  
9 12     12   1541 use namespace::clean;
  12         9806  
  12         46  
10              
11             extends 'Statistics::R::REXP';
12              
13              
14 12     12   1550 use constant sexptype => 'CLOSXP';
  12         14  
  12         1616  
15              
16             has args => (
17             is => 'ro',
18             default => sub { [] },
19             );
20              
21             has defaults => (
22             is => 'ro',
23             default => sub { [] },
24             );
25              
26             has body => (
27             is => 'ro',
28             );
29              
30             has environment => (
31             is => 'ro',
32             );
33              
34              
35             use overload
36             '""' => sub {
37 2     2   288 my $self = shift;
38 2         3 'function('. join(', ', @{$self->args}) . ') ' . $self->body
  2         43  
39 12     12   942 };
  12         712  
  12         82  
40              
41              
42             sub BUILDARGS {
43 71     71 0 3603 my $class = shift;
44 71 100       188 if ( scalar @_ == 1 ) {
    100          
45 2 50 66     21 if ( ref $_[0] eq 'HASH' ) {
    100          
46 0         0 return $_[0];
47             } elsif ( blessed $_[0] && $_[0]->isa('Statistics::R::REXP::Closure') ) {
48             # copy constructor from another closure
49 1         22 return { args => $_[0]->args,
50             defaults => $_[0]->defaults,
51             body => $_[0]->body,
52             environment => $_[0]->environment };
53             }
54 1         8 die "Single parameters to new() must be a HASH data"
55             ." or a Statistics::R::REXP::Closure object => ". $_[0] ."\n";
56             }
57             elsif ( @_ % 2 ) {
58 1         8 die "The new() method for $class expects a hash reference or a key/value list."
59             . " You passed an odd number of arguments\n";
60             }
61             else {
62 68         213 return {@_};
63             }
64             }
65              
66              
67             sub BUILD {
68 68     68 0 1564 my ($self, $args) = (shift, shift);
69              
70             # Required attribute
71 68 100       144 die 'Attribute (body) is required' unless defined $args->{body};
72            
73             # Required attribute type
74             die "Attribute 'args' must be a reference to an array of scalars" if ref($self->args) ne 'ARRAY' ||
75 67 50 33     1032 grep { ref $_ } @{$self->args};
  57         165  
  67         1179  
76            
77             die "Attribute 'defaults' must be a reference to an array of REXPs" if ref($self->defaults) ne 'ARRAY' ||
78 67 100 33     1136 grep { defined($_) && ! (blessed($_) && $_->isa('Statistics::R::REXP')) } @{$self->defaults};
  41 50 33     324  
  67         1159  
79            
80 67 100 66     1261 die "Attribute 'body' must be a reference to an instance of Statistics::R::REXP" unless
81             blessed($self->body) && $self->body->isa('Statistics::R::REXP');
82            
83 66 100 66     2390 die "Attribute 'environment' must be an instance of Environment" if defined $self->environment &&
      100        
84             !(blessed($self->environment) && $self->environment->isa('Statistics::R::REXP::Environment'));
85            
86 65         2147 my $defaults_length = @{$self->defaults};
  65         872  
87 65 100       303 if ($defaults_length) {
88             die 'argument names don\'t match their defaults'
89 17 100       22 unless $defaults_length == @{$self->args}
  17         240  
90             }
91             }
92              
93             around _eq => sub {
94             my $orig = shift;
95             return unless $orig->(@_);
96             my ($self, $obj) = (shift, shift);
97             Statistics::R::REXP::_compare_deeply($self->args, $obj->args) &&
98             ((scalar(grep {$_} @{$self->defaults}) == scalar(grep {$_} @{$obj->defaults})) ||
99             Statistics::R::REXP::_compare_deeply($self->defaults, $obj->defaults)) &&
100             Statistics::R::REXP::_compare_deeply($self->body, $obj->body) &&
101             Statistics::R::REXP::_compare_deeply($self->environment, $obj->environment)
102             };
103              
104              
105             sub to_pl {
106 1     1 1 560 die "Closures do not have a native Perl representation"
107             }
108              
109              
110             1; # End of Statistics::R::REXP::Closure
111              
112             __END__