I'm not sure what the expected output is, but I'll probably avoid using
eval.
#!/usr/bin/perl
use warnings;
use strict;
use feature qw{ say };
sub evaluate_row {
my ($rules, $row) = @_;
for my $column (keys %$row) {
if (exists $rules->{$column}) {
return 0 unless $rules->{$column}($row->{$column});
}
}
return 1
}
sub is_greater_to_0 { $_[0] > 0 }
sub is_even { 0 == $_[0] % 2 }
my $rules = {a => \&is_greater_to_0,
b => \&is_even};
my @rows = ({a => 1, b => 2},
{a => 0, b => 2},
{a => 1, b => 3},
{a => 0, b => 3});
for my $row (@rows) {
say evaluate_row($rules, $row) ? 'ACCEPTED' : 'REJECTED';
}
In fact, as you'll probably use the same rules for all the rows, initialising an object with the rules as the constructor argument makes even more sense. It moves us a bit farther from the initial example, but here it is:
#!/usr/bin/perl
use warnings;
use strict;
use feature qw{ say };
{ package My::RowChecker;
sub new {
my ($class, $rules) = @_;
die 'Rules should be a hash' unless ref {} eq ref $rules;
return bless {rules => $rules}, $class
}
sub check {
my ($self, $row) = @_;
for my $column (keys %$row) {
if (exists $self->{rules}{$column}) {
return 0 unless $self->{rules}{$column}($row->{$column
+});
}
}
return 1
}
}
sub is_greater_to_0 { $_[0] > 0 }
sub is_even { 0 == $_[0] % 2 }
my $checker = 'My::RowChecker'->new({a => \&is_greater_to_0,
b => \&is_even});
my @rows = ({a => 1, b => 2},
{a => 0, b => 2},
{a => 1, b => 3},
{a => 0, b => 3});
for my $row (@rows) {
say $checker->check($row) ? 'ACCEPTED' : 'REJECTED';
}
You can also use an object orientation system to implement the class, e.g. Moo:
#!/usr/bin/perl
use warnings;
use strict;
use feature qw{ say };
{ package My::RowChecker;
use Moo;
use Types::Standard qw( HashRef CodeRef );
has rules => (is => 'ro',
required => 1,
isa => HashRef[CodeRef]);
sub check {
my ($self, $row) = @_;
for my $column (keys %$row) {
if (exists $self->rules->{$column}) {
return 0 unless $self->rules->{$column}($row->{$column
+});
}
}
return 1
}
}
sub is_greater_to_0 { $_[0] > 0 }
sub is_even { 0 == $_[0] % 2 }
my $checker = 'My::RowChecker'->new(rules => {a => \&is_greater_to_0,
b => \&is_even});
my @rows = ({a => 1, b => 2},
{a => 0, b => 2},
{a => 1, b => 3},
{a => 0, b => 3});
for my $row (@rows) {
say $checker->check($row) ? 'ACCEPTED' : 'REJECTED';
}
Updated: Used named subs.
Update 2: Added the OO examples.
map{substr$_->[0],$_->[1]||0,1}[\*||{},3],[[]],[ref qr-1,-,-1],[{}],[sub{}^*ARGV,3]