В этом случае нет необходимости использовать строковую форму eval
(или любую другую форму в этом отношении).Это не только медленно, но и может молча перехватывать ошибки и может привести к выполнению ненадежного кода, если используется с испорченным вводом.Чтобы написать вызов виртуальной функции в Perl, вы можете либо напрямую работать с таблицей символов, либо использовать символическую ссылку:
use 5.010;
use warnings;
use strict;
{package HashValidator;
sub test_ok {exists $_[0]{ok}}
sub test_fail {exists $_[0]{fail}}
}
my $hashref = {ok => 1};
my $errors;
for my $vFunction qw(test_ok test_fail) {
# to call the function:
say "glob deref: $vFunction: ", $HashValidator::{$vFunction}->($hashref);
{no strict 'refs';
say "symbolic: $vFunction: ", &{"HashValidator::$vFunction"}($hashref)}
# to conditionally use the result (if it is a true boolean value):
if (my $ret = $HashValidator::{$vFunction}->($hashref)) {
push @$errors, $ret;
}
# or to keep the function call in list context:
push @$errors, grep $_, $HashValidator::{$vFunction}->($hashref);
# or to golf it:
push @$errors, $HashValidator::{$vFunction}->($hashref) || ();
}
say @$errors.': ', join ', ' => @$errors;
, которая печатает:
glob deref: test_ok: 1
symbolic: test_ok: 1
glob deref: test_fail:
symbolic: test_fail:
3: 1, 1, 1
Если вы работаетес объектно-ориентированным кодом вызовы виртуальных методов еще проще, без таблицы символов или символических ссылок:
$obj->$vMethod(...)