Como posso avaliar expressões encadeadas de uma corda, em Perl?
-
22-07-2019 - |
Pergunta
Eu não sou realmente certo o que chamar este tipo de expressões, portanto, um exemplo seria mais fácil ...
Existe uma maneira em Perl para avaliar expressões como a < b <= c
? Eu tenho um arquivo de configuração que permite que o usuário forneça expressões condicionais para determinadas ações. Ao invés de divisão do estado em duas partes (como eu faria normalmente no código), eu gostaria de representá-lo desta forma, se possível.
Solução
Isso está vindo em Perl 6, com certeza. Mas, infelizmente, eu não acho que é uma das coisas de Perl 6 emprestados por Perl 5.10.
Outras dicas
acorrentados comparações são caracterizados em Perl 6.
Agora, faria será possível criar uma sub-rotina de encadeamento para Perl 5.x ? Essa é uma pergunta interessante ...
Este é um pouco menos legível, mas realiza o que você quer: a < b && b <= c
Como já foi mencionado Perl5 não (ainda) ter acorrentado comparações.
No entanto, se você estiver analisando "a
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" }
}
}
Seu somente um exemplo rudimentar (ie. Não é completa e nenhuma verificação de erros), mas eu acho que você começa a idéia.
E você pode encontrar algo parecido com isso já no CPAN
. Algo como Parse::RPN
talvez um bloco de construção útil.
Agora, se você pergunta é sobre como a < b <= c
então, literalmente parse que é outra chaleira de peixes!
/ I3az /
ignorando qualquer validação de entrada ou execução da eventual comparação para o momento, o código a seguir (ou uma variação menor do mesmo) deve ser capaz de reescrever sua declaração:
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