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.0001';
4 14     14   19452 use 5.010;
  14         27  
5              
6 14     14   43 use Scalar::Util qw(refaddr blessed);
  14         12  
  14         602  
7              
8 14     14   475 use Class::Tiny::Antlers qw(-default around);
  14         4131  
  14         60  
9 14     14   1783 use namespace::clean;
  14         9792  
  14         58  
10              
11             extends 'Statistics::R::REXP';
12              
13              
14 14     14   1744 use constant sexptype => 'CLOSXP';
  14         19  
  14         1768  
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   319 my $self = shift;
38 2         3 'function('. join(', ', @{$self->args}) . ') ' . $self->body
  2         43  
39 14     14   968 };
  14         730  
  14         80  
40              
41              
42             sub BUILDARGS {
43 78     78 0 3194 my $class = shift;
44 78 100       207 if ( scalar @_ == 1 ) {
    100          
45 2 50 66     19 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         21 return { args => $_[0]->args,
50             defaults => $_[0]->defaults,
51             body => $_[0]->body,
52             environment => $_[0]->environment };
53             }
54 1         7 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         6 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 75         217 return {@_};
63             }
64             }
65              
66              
67             sub BUILD {
68 75     75 0 1861 my ($self, $args) = (shift, shift);
69              
70             # Required attribute
71 75 100       157 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 74 50 33     1120 grep { ref $_ } @{$self->args};
  64         195  
  74         1324  
76            
77             die "Attribute 'defaults' must be a reference to an array of REXPs" if ref($self->defaults) ne 'ARRAY' ||
78 74 100 33     1274 grep { defined($_) && ! (blessed($_) && $_->isa('Statistics::R::REXP')) } @{$self->defaults};
  46 50 33     351  
  74         1238  
79            
80 74 100 66     1285 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 73 100 66     2678 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 72         2499 my $defaults_length = @{$self->defaults};
  72         1004  
87 72 100       334 if ($defaults_length) {
88             die 'argument names don\'t match their defaults'
89 19 100       19 unless $defaults_length == @{$self->args}
  19         281  
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 478 die "Closures do not have a native Perl representation"
107             }
108              
109              
110             1; # End of Statistics::R::REXP::Closure
111              
112             __END__