Come posso valutare espressioni concatenate da una stringa, in Perl?
-
22-07-2019 - |
Domanda
Non sono davvero sicuro di come chiamare questo tipo di espressioni, quindi un esempio sarebbe più facile ...
Esiste un modo in Perl per valutare espressioni come a < b <= c
? Ho un file di configurazione che consente all'utente di fornire espressioni condizionali per determinate azioni. Invece di dividere la condizione in due parti (come farei normalmente nel codice), vorrei rappresentarla in questo modo, se possibile.
Soluzione
Questo arriverà sicuramente in Perl 6. Ma sfortunatamente, non credo sia una delle cose di Perl 6 prese in prestito da Perl 5.10.
Altri suggerimenti
Confronti concatenati sono presenti in Perl 6.
Ora, sarebbe è possibile creare una sub-routine concatenata per Perl 5.x ? Questa è una domanda interessante ...
Questo è leggermente meno leggibile, ma realizza ciò che vuoi: a < b && b <= c
Come altri hanno già detto, Perl5 non ha (ancora) confronti concatenati.
Tuttavia, se stai analizzando " a < b < = c " da un file di configurazione e vuoi solo valutarlo, allora forse questo è quello che ti serve dopo?
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" }
}
}
È solo un esempio rudimentale (cioè non completo e nessun controllo degli errori) ma penso che tu abbia avuto l'idea.
E potresti trovare qualcosa del genere già su CPAN
. Qualcosa come Parse::RPN
forse un utile blocco di costruzione.
Ora, se hai domande su come analizzare letteralmente a < b <= c
, questo è un altro bollitore per pesci!
/ I3az /
ignorando qualsiasi convalida di input o esecuzione dell'eventuale confronto per il momento, il seguente codice (o una sua variante minore) dovrebbe essere in grado di riscrivere la tua dichiarazione:
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