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

Forgive me, monks. My copy of Learning Perl, The Perl Cookbook, and Programming Perl is buried in a storage locker.

I'm currently working on a simple script that watches for processing that hog the CPU. I'm not really interested in monitoring CPU time. I want to take the "ps" output from a Linux system, snap up the PIDs of processes "currently" using > $percentage of the CPU, sleep for a bit, and repeat the process. After a few loops, I want to kill these processes.

I'm getting stuck at using a custom if() statement. I have a neat and clean variable at the top of the script:
$operator = '> 98.0';

This doesn't seem to work in this context:
if ($consumption $operator) { do something; }

I know there's a way to achieve this, but I don't remember how. Any help, is as always, very much appreciated.

Thanks guys!
  • Comment on Using dynamic operators in an if() statement

Replies are listed 'Best First'.
Re: Using dynamic operators in an if() statement
by sgifford (Prior) on Aug 22, 2006 at 04:57 UTC
    I think what you're looking for is a string eval, which would be something like this:
    if (eval "\$consumption $operator")

    But I wouldn't recommend you do that. It means any errors in $operator will be runtime instead of compile-time errors, and that code will be re-compiled every time through your loop, which is bad for performance.

    Instead, consider customizing your condition with a small sub, something like:

    sub process_match { my($consumption)=@_; return $consumption > 98.0; } if (process_match($consumption)) { do something; }
    This gives you the same flexibility without any of the downsides of string eval.

    Good luck!

    Update: $consumption should be escaped in eval. Thanks, ikegami!

      Yes, this is a very good approach. To expand on it, you could even dispatch to multiple selection functions based on other criteria (the OP doesn't make clear what the criteria are, but hints at them). Something like this (untested) example:

      my %match = ( high => sub { $_[0] > 98.0 }, low => sub { $_[0] < 55.0 }, exact => sub { $_[0] = 77.0 }, ); # ...later... my $test = decide_somehow(); if ($match{$test}->($consumption)) { print "Test $test succeeded\n"; do_something(); };
      There are other ways to generalize the approach; this is just an example that may or may not be appropriate, depending on other program constraints.

Re: Using dynamic operators in an if() statement
by GrandFather (Saint) on Aug 22, 2006 at 04:37 UTC

    Why not simply:

    ... use constant THRESHOLD => 98.0; ... if ($consumption > THRESHOLD) { # do something }

    DWIM is Perl's answer to Gödel
Re: Using dynamic operators in an if() statement
by Zaxo (Archbishop) on Aug 22, 2006 at 04:55 UTC

    I think you're trying to remember,

    my $operator = '> 98.0'; if ( eval $consumption . $operator ) { }
    I think that absorbing the operator into a string to be eval'd doesn't get you anything you want. I'd prefer,
    sub LIMIT () { 98.0 } if ($consumption > LIMIT) { }

    After Compline,
    Zaxo

      Shouldn't that be

      if ( eval "\$consumption $operator" )

      I doubt the existance of a need to stringify and evaluate the contents of $consumption.

Re: Using dynamic operators in an if() statement
by aquarium (Curate) on Aug 22, 2006 at 12:57 UTC
    reason why it doesn't work is that '> 98.0' is a string...not an operator and a value, unless you eval it. Therefore the "if" statement sees a list of two strings, and evaluates the list, which returns number of elements in list in scalar contenxt, which is equal to "2". "2" means TRUE in perl so the "if" always calls the sub. if the operator is always ">" then why on earth would you try to codify it into a variable? There's no need to be fancy, so just code it simple...and we can all go home :)
    if($consumption > $threshold) {do something;}
    the hardest line to type correctly is: stty erase ^H