Preceptor has asked for the wisdom of the Perl Monks concerning the following question:

The question cropped up on a mailing list, which struck me as being an interesting one to repost here.
As part of a script the person in question is trying to do something along the lines of
$a= 10; $b= 20; $operator= ">=" if ( $a $operator $b ) { ... }
operator, a and b are parameters read from a file.
Perl doesn't like that syntax (well, the obvious immediate reason is that 'operator' is a string rather than an actual operator but you see what I'm trying to accomplish). Now whilst it's possible to do a 'case' style statement, it struck me that that's far from an elegant way of doing things. Can someone suggest a proper perlish way of accomplishing this?
Cheers.
--
It's not pessimism if there is a worse option, it's not paranoia when they are and it's not cynicism when you're right.

Replies are listed 'Best First'.
Re: Dynamic operators
by davorg (Chancellor) on Sep 11, 2002 at 08:01 UTC

    You could do it using eval.

    my $a = 10; my $b = 20; my $op = '>='; if (eval "$a $op $b") { print "true\n"; } else { print "false\n"; }
    --
    <http://www.dave.org.uk>

    "The first rule of Perl club is you do not talk about Perl club."
    -- Chip Salzenberg

      if (eval "$a $op $b") {

      if (eval "\$a $op \$b") {
      Makes life easier.

      - Yes, I reinvent wheels.
      - Spam: Visit eurotraQ.
      

Re: Dynamic operators
by Chmrr (Vicar) on Sep 11, 2002 at 08:33 UTC

    Eval is probably the way to go with this, as others have shown. For extra style points, make it into an anonymous sub so as to ensure that the overhead of eval only happens once:

    sub makeop { my $op = shift; return eval 'sub {$_[0] '.$op.' $_[1]}'; } my $x = 42; my $y = 50; my $op = makeop(">="); if ($op->($x, $y)) { ... }

    perl -pe '"I lo*`+$^X$\"$]!$/"=~m%(.*)%s;$_=$1;y^`+*^e v^#$&V"+@( NO CARRIER'

      Didn't I read that in Perl6, all the built-in operators could have references taken to them? So, you would not need to make your own closure, but would use some new syntax to refer to the one that exists. However, you might still need an eval to do that, if there is no "symbolic ref" way to look up the builtin.

Re: Dynamic operators
by kabel (Chaplain) on Sep 11, 2002 at 08:02 UTC
    please do NOT use $a and $b since this variables are reserved for use with sort. you can use the eval call:
    use strict; my $n1= 10; my $n2= 20; my $operator= "=="; my $expr = "$n1 $operator $n2"; my $erg = eval $expr; die if ($@); if ($erg) { print "true\n"; } else { print "false\n"; }
      While you have a valid point, the variables are not "reserved", they are simply used. Avoiding them is a good way to avoid really hard to track down errors, but if sort() is not used then they are fine.

      --- demerphq
      my friends call me, usually because I'm late....

        they are not just simply used since strict.pm for example does not "check" them. another point is that any programmer shots himself/herself in the foot when using such imaginable variable names - except sort of course. variable names with a length less than, say, 4 should generally be disallowed. but that is only my opinion. ;)