How can I 开发者_开发问答dynamically pass eq or ne inside perl if statement? I tried below but is not working:
my $this="this";
my $that="that";
my $cond='ne';
if($this eval($cond) $that)
{
print "$cond\n";
}
You don't need eval
for this. Just use a dispatch table:
sub test {
my %op = (
eq => sub { $_[0] eq $_[1] },
ne => sub { $_[0] ne $_[1] },
);
return $op{ $_[2] }->($_[0], $_[1]);
}
if (test($this, $that, $cond)){
print "$cond\n";
}
if (($cond eq 'eq') xor ($this ne $that)) {
print $cond;
};
But maybe a better and more general approach would be to use perl's functional capabilities and create a hash table of functions:
my %compare = (
eq => sub {shift eq shift},
ne => sub {shift ne shift},
lt => sub {shift lt shift},
like => sub {$_[0] =~ /$_[1]/},
# ....
);
#...
if ($compare{$cond}->($this, $that)) {
print $cond;
};
Whenever you are using eval
for runtime code generation, it is best to keep in mind a few details. First, eval
is dangerous, so you should eval
the smallest, most generic code you can, and check for errors. Second, eval
is slow, so you should store the result for later.
{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";
}
Here the compare
function will build a new coderef (with eval
) when it sees an operator that it has not had yet. The return value of the eval
is checked, and an error is raised if anything when wrong.
This coderef (which expects its values as arguments) is stored in %cache
. Then the cached coderef is run with the two values as arguments. This same coderef will be used over and over whenever the same operator is used.
精彩评论