¿Cómo puedo evaluar expresiones encadenadas de una cadena, en Perl?
-
22-07-2019 - |
Pregunta
No estoy realmente seguro de cómo llamar a este tipo de expresiones, por lo que un ejemplo sería más fácil ...
¿Hay alguna manera en Perl para evaluar expresiones como a < b <= c
? Tengo un archivo de configuración que permite al usuario proporcionar expresiones condicionales para ciertas acciones. En lugar de dividir la condición en dos partes (como lo haría normalmente en el código), me gustaría representarla de esta manera, si es posible.
Solución
Eso viene en Perl 6, seguro. Pero desafortunadamente, no creo que sea una de las cosas de Perl 6 prestado por Perl 5.10.
Otros consejos
Las comparaciones encadenadas se muestran en Perl 6.
Ahora, haría Sería posible crear una subrutina de conexión en cadena para Perl 5.x ? Esa es una pregunta interesante ...
Esto es un poco menos legible, pero logra lo que desea: a < b && b <= c
Como otros han mencionado, Perl5 (todavía) no tiene comparaciones encadenadas.
Sin embargo, si está analizando " a < b < = c " desde un archivo de configuración y solo quiero evaluarlo, entonces ¿quizás esto sea lo que buscas?
use strict;
use warnings;
use 5.010;
my ($a, $b, $c) = (10, 20, 30);
say 'Its true!' if comparison( $a, '<', $b, '<=', $c );
sub comparison {
my $left = shift;
while (my $cmp = shift) {
my $right = shift;
compare( $cmp, $left, $right ) or return;
$left = $right;
}
return 1;
}
sub compare {
my $op = shift;
given ($op) {
when ( '<' ) { return $_[0] < $_[1] }
when ( '<=' ) { return $_[0] <= $_[1] }
default { die "Invalid comparison operator" }
}
}
Es solo un ejemplo rudimentario (es decir, no está completo y no hay verificación de errores), pero creo que se entiende la idea.
Y es posible que ya encuentre algo como esto en CPAN
. Algo así como Parse::RPN
puede ser un elemento útil.
Ahora, si tu pregunta es sobre cómo analizar literalmente a < b <= c
¡entonces ese es otro caldero de pescado!
/ I3az /
ignorando cualquier validación de entrada o ejecución de la comparación eventual por el momento, el siguiente código (o una variación menor de este) debería poder reescribir su declaración:
sub rewrite {
my $str = shift;
my $ops = join "|" => qw/ < > <= >= == != /;
1 while $str =~ s/ ($ops) \s* (\w+?) \s* ($ops) /$1 $2 && $2 $3/xg;
$str
}
print rewrite "a < b < 5 < c != d";
# prints a < b && b < 5 && 5 < c && c != d