views:

136

answers:

5

I'm not really sure what to call these type of expressions, so an example would be easier...

Is there a way in Perl to evaluate expressions like a < b <= c? I have a configuration file that allows the user to provide conditional expressions for certain actions. Rather than splitting the condition into two parts (as I would normally do in code), I'd like to represent it this way, if possible.

+2  A: 

That's coming in Perl 6, for sure. But unfortunately, I don't think it's one of the things from Perl 6 borrowed by Perl 5.10.

AmbroseChapel
+2  A: 

Chained comparisons are featured in Perl 6.

Now, would it be possible to create a daisy-chaining sub-routine for Perl 5.x? That's an interesting question...

Zaid
A: 

This is slightly less readable, but accomplishes what you want: a < b && b <= c

glenn jackman
A: 

As others have mentioned Perl5 doesn't (yet) have chained comparisons.

However if you are parsing "a < b <= c" from a config file and just want to evaluate it then perhaps this maybe what your steering after?

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" }
    }
}

Its only a rudimentary example (ie. not complete and no error checking) but I think you get the idea.

And you may find something like this already on CPAN. Something like Parse::RPN maybe a useful building block.

Now if you question is about how to literally parse a < b <= c then that is another kettle of fish!

/I3az/

draegtun
A: 

ignoring any input validation or execution of the eventual comparison for the moment, the following code (or a minor variation of it) should be able to rewrite your statement:

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
Eric Strom