あなたがしようとしているのは、'$degree>=5' を実際のコードとして評価することです。文字列をコードとして評価しようとする (これはevalで実行できます) よりも、代わりにコード参照を渡す方が通常は安全で、多くの場合より堅牢です。次のように、generator サブルーチンを使用して、オンデマンドで条件付きサブルーチンを生成できます。
sub generate_condition {
my ( $test, $bound ) = @_;
return sub { return $test >= $bound; };
}
my %condition;
$condition{'hub'}{'1'} = generate_condition( $degree, 5 );
if( $condition{$parameter}{1}->() ) { ... }
>=
(つまり、リレーションシップ自体) も動的に作成する場合は、もう少し注意が必要です。次に、いくつかの選択肢があります。1つは、すべてのリスクを伴うstringy evalに戻ります(特に、ユーザーに文字列を指定させ始めた場合)。generate_condition()
もう 1 つは、サブ内のルックアップ テーブルです。
generate_condition()
呼び出されると、作成時にバインドされた条件を評価するサブルーチン参照を返します。
これは、Perl の任意の条件を受け入れ、テスト対象の引数と一緒にサブルーチンにラップする一般化されたソリューションです。その後、subref を呼び出して条件を評価できます。
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";
このようなものを構築するとき、サブルーチンの製造時ではなく、呼び出し時にバインドするために 1 つのパラメーターを開いたままにしておくことに関心があることがよくあります。$bound
" " と "$relation" パラメータのみをバインドしたいが、" "$test
はサブルーチンの呼び出し時に仕様のために開いたままにしておくとします。サブ世代を次のように変更します。
sub generate_condition {
my ( $relation, $bound ) = @_;
die "Bad relationship\n"
if ! $relation =~ m/^(?:<=?|>=?|==|l[te]|g[te]|cmp)$/;
state $relationships = {
'<' => sub { return $_[0] < $bound },
# ......
そして、次のように呼び出します。
my $condition = generate_condition( '<', 5 );
if( $condition->(2) ) {
print "Yes, 2 is less than 5\n";
}
リレーショナル評価で左辺と右辺の両方の遅延バインディングを提供することが目標である場合、これは機能します。
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"; }
この種のツールは関数型プログラミングのカテゴリに分類され、Mark Jason Dominus の著書Higher Order Perlで美しく詳細に説明されています。