Sie versuchen, '$ Grad> = 5' als echten Code zu bewerten. Anstatt zu versuchen, die Zeichenfolge als Code auszuwerten (was mit eval erledigt werden kann), ist es normalerweise sicherer und oft robuster, stattdessen eine Codereferenz zu übergeben. Sie können einen Generator-Unterprogramm verwenden, um bedingte U-Boote auf Nachfrage zu erzeugen, wie folgt aus:
sub generate_condition {
my ($test, $bound) = @_;
return sub { return $test >= $bound; };
}
my %condition;
$condition{'hub'}{'1'} = generate_condition($degree, 5);
if($condition{$parameter}{1}->()) { ... }
Es ist ein wenig komplizierter wird, wenn Sie die >=
(dh die Beziehung selbst) wollen auch dynamisch erstellt werden. Dann haben Sie ein paar Möglichkeiten. Man bringt Sie zurück zu Stringy Eval, mit all seinen Risiken (besonders, wenn Sie beginnen, Ihren Benutzer die Zeichenfolge angeben zu lassen). Die andere wäre eine Nachschlagetabelle in Ihrem generate_condition()
Sub.
generate_condition()
gibt eine Subroutinenreferenz zurück, die bei Aufruf die Bedingung auswertet, die zur Erstellungszeit gebunden wurde.
Hier ist eine verallgemeinerte Lösung, die alle Bedingungen von Perl akzeptiert und sie zusammen mit den getesteten Argumenten in eine Subroutine einfügt. Die Subref kann dann aufgerufen werden, um die Bedingung zu bewerten:
use strict;
use warnings;
use feature qw/state/;
sub generate_condition {
my ($test, $relation, $bound) = @_;
die "Bad relationship\n"
if ! $relation =~ m/^(?:<=?|>=?|==|l[te]|g[te]|cmp)$/;
state $relationships = {
'<' => sub { return $test < $bound },
'<=' => sub { return $test <= $bound },
'==' => sub { return $test == $bound },
'>=' => sub { return $test >= $bound },
'>' => sub { return $test > $bound },
'<=>' => sub { return $test <=> $bound },
'lt' => sub { return $test lt $bound },
'le' => sub { return $test le $bound },
'eq' => sub { return $test eq $bound },
'ge' => sub { return $test ge $bound },
'gt' => sub { return $test gt $bound },
'cmp' => sub { return $test cmp $bound },
};
return $relationships->{$relation};
}
my $true_condition = generate_condition(10, '>', 5);
my $false_condition = generate_condition('flower', 'eq', 'stamp');
print '10 is greater than 5: ',
$true_condition->() ? "true\n" : "false\n";
print '"flower" is equal to "stamp": ',
$false_condition->() ? "true\n" : "false\n";
Oft, wenn man diese Art von Dingen konstruiert ein in Verlassen einen Parameters offen interessiert ist bei Call-Zeit zu binden, anstatt bei Unterprogramm Herstellung Zeit.Angenommen, Sie möchten nur die Parameter "$bound
" und "$ relation" binden, aber lassen Sie "$test
" zur Zeit des Unterprogrammaufrufs offen für die Spezifikation.
sub generate_condition {
my ($relation, $bound) = @_;
die "Bad relationship\n"
if ! $relation =~ m/^(?:<=?|>=?|==|l[te]|g[te]|cmp)$/;
state $relationships = {
'<' => sub { return $_[0] < $bound },
# ......
Und dann es wie folgt aufrufen: Sie würden Ihre Unter Generation wie diese ändern
my $condition = generate_condition('<', 5);
if($condition->(2)) {
print "Yes, 2 is less than 5\n";
}
Wenn das Ziel die späte Bindung sowohl in der relationalen Auswertung der linken und rechten Seite zu schaffen, dies funktioniert:
sub generate_condition {
my $relation = shift;
die "Bad relationship\n"
if ! $relation =~ m/^(?:<=?|>=?|==|l[te]|g[te]|cmp)$/;
state $relationships = {
'<' => sub { return $_[0] < $_[1] },
'<=' => sub { return $_[0] <= $_[1] },
# ...... and so on .....
return $relationship->($relation);
}
my $condition = generate_condition('<');
if($condition->(2,10)) { print "True.\n"; }
diese Art von Werkzeug in die Kategorie der funktionalen Programmierung fällt, und befindet sich im schönen Detail in Mark Jason Dominus Buchbedeckt
meinst du $ condition {'hub'} {'1'} = '$ degree => 5'; ? – squiguy