Lo que intenta hacer es evaluar '$ degree> = 5' como código real. En lugar de tratar de evaluar la cadena como código (que se puede hacer con eval), generalmente es más seguro y, a menudo más robusto, en cambio pasa una referencia de código. Se puede utilizar una subrutina generador para generar submarinos condicionadas a la demanda, así:
sub generate_condition {
my ($test, $bound) = @_;
return sub { return $test >= $bound; };
}
my %condition;
$condition{'hub'}{'1'} = generate_condition($degree, 5);
if($condition{$parameter}{1}->()) { ... }
Se pone un poco más complicado si desea que el >=
(es decir, la relación en sí) que se crea de forma dinámica también. Entonces tienes un par de opciones. Uno lo lleva de vuelta a la evaluación fibrosa, con todos sus riesgos (especialmente si comienza a permitir que su usuario especifique la cadena). El otro sería una tabla de búsqueda dentro de su sub generate_condition()
.
generate_condition()
devuelve una referencia de subrutina que, cuando se invoca, evaluará la condición que estaba vinculada en el momento de la creación.
Aquí hay una solución generalizada que aceptará cualquiera de los condicionales de Perl y los envolverá junto con los argumentos probados en una subrutina. El subref continuación, se puede invocar para evaluar el condicional:
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";
A menudo, cuando se construye este tipo de cosas que uno está interesado en dejar un parámetro abierta para unirse a las llamadas en tiempo en lugar de en la producción subrutina tiempo.Supongamos que solo desea vincular los parámetros "$bound
" y "$ relation", pero deje "$test
" abierto para la especificación en el momento de la llamada a la subrutina. Se podría modificar su sub generación de la siguiente manera:
sub generate_condition {
my ($relation, $bound) = @_;
die "Bad relationship\n"
if ! $relation =~ m/^(?:<=?|>=?|==|l[te]|g[te]|cmp)$/;
state $relationships = {
'<' => sub { return $_[0] < $bound },
# ......
e invocarla como esto:
my $condition = generate_condition('<', 5);
if($condition->(2)) {
print "Yes, 2 is less than 5\n";
}
Si el objetivo es proporcionar el enlace en tiempo tanto de la izquierda y el lado derecho en la evaluación relacional, esto va a funcionar:
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"; }
este tipo de herramienta entra en la categoría de programación funcional, y está cubierta con profusión de detalles en el libro de MarkJason Dominus
te refieres $ condition {'hub'} {'1'} = '$ degree => 5'; ? – squiguy