Всякий раз, когда вы используете eval
для генерации кода во время выполнения, лучше помнить несколько деталей. Во-первых, eval
опасно, поэтому вы должны eval
самый маленький, самый общий код, который вы можете, и проверять на наличие ошибок. Во-вторых, eval
медленный, поэтому вы должны сохранить результат на потом.
{my %cache;
sub compare {
my ($x, $op, $y) = @_;
$cache{$op} ||= eval "sub {\$_[0] $op \$_[1]}" || die "bad op: $op\n";
$cache{$op}->($x, $y)
}}
my $this="this";
my $that="that";
my $cond='ne';
if (compare $this, $cond, $that) {
print "$cond\n";
}
Здесь функция compare
создаст новую кодовую ссылку (с eval
), когда увидит оператора, которого еще не было. Возвращаемое значение eval
проверяется, и возникает ошибка, если что-то не так.
Этот код ссылки (который ожидает свои значения в качестве аргументов) хранится в %cache
. Затем кешированный код запускается с двумя значениями в качестве аргументов. Один и тот же код будет использоваться снова и снова, когда используется один и тот же оператор.