2

Is it possible in Perl to use a function's return value as the expression in an "if" statement? For example; in C I can write

if (!myFunction()){
   printf("myFunction returned false.\n");
} else {
   printf("myFunction returned true\n");
}

But in perl I find I must go through the pain of ..

$ret = myFunction();
if (!$ret){
    print "myFunction returned false.\n";
}

I know as soon as I post this someone will redirect me to several other posts of this question. But, obviously, I could not find what I'm looking for or I would not write this! So spare me the "have you tried searching for ...." messages!

Here is what myFunction() looks like.

sub myFunction
{
    my ($run, $runTime) = @_;
    my ($code);

    eval {
        $SIG{ALRM} = sub {die "Operation Timed Out";};

        alarm($run_time);
        $EXIT_STR = `$run`; # Execute $run and save output in EXIT_STR
        $code = $?;         # Save cmd exit code.
        $EXIT_CODE = $code; # Set a global value (EXIT_CODE)
        alarm(0);
        return($code);
    };
    if ($@) {
        if ($@ =~ /Operation Timed Out/) { 
            print "Time out\n";
            return(10);
        }
    }
}

After everyone's feedback I went back to the books to learn more about eval. After a bit of reading it was clearer that "eval" "returned" a value to the function it was part of. It was then up to me to decide what to do with the eval results. With that in mind I made some changes and the function works as I had hoped. Thanks to all!

10
  • Yes, that works just fine in Perl. You didn't show us what your myFunction looks like, but the problem will be in there. Commented Jul 24, 2014 at 21:30
  • 3
    The extra variable is not required in perl.. what's the real problem? Make sure to include any actual messages/error indicators. Commented Jul 24, 2014 at 21:32
  • 1
    Please, show the EXACT example of myFunction. It simply works in perl, despite the long answers, it is mostly very intuitive. So, isn't possible to tell anything more without your code-example. Commented Jul 24, 2014 at 22:04
  • 1
    You know, if you have a return in an eval in a sub, the return doesn't return a value from the sub - it returns a value from the eval. Commented Jul 24, 2014 at 22:34
  • 1
    When you will use the recommended use strict; use warnings; you will catch the typo $runTime vs $run_time. You didn't return the result of eval. In the last if, what is returned when the $@ isnt a Timed out? - many issues... Commented Jul 24, 2014 at 22:39

4 Answers 4

1

Yup.

Wait. I can't give such a short answer...

Yes. If a function is inside an if statement, Perl will take the return value of the function as a boolean value. If the return value is zero, a blank string, a null value, a null string, or an undef, the if statement will be considered false. Otherwise, the if statement will be considered true.

Here's an easy to understand example:

if ( not is_odd( $number ) ) {
    print "$number is divisible by two\n";
}

sub is_odd {
    my $number = shift;
    return $number % 2;   # Modulo arithmetic
}

In the above $number % 2 will return zero on even numbers and one on odd numbers.

It's a good question. The best thing to do is to write a small script to try it out. Play around with it a bit:

For example. Let's add a second function we can use:

sub is_even {
    my $number = shift;
    return not is_odd( $number );
}

What does this return? How does this work in an if statement?

Sign up to request clarification or add additional context in comments.

Comments

0

This will work fine.

The only caveat is that using it in an if-statement will provide scalar context to the return value so if something non-scalar is returned, it will get scalarized before the if condition is evaluated.

Comments

0

You may need to explicitly return a false value in cases where you don't want the function to return True. Remember that perl functions will return the last evaluated statement in the absence of a real return value. So, take this example:

#!/usr/bin/perl

use warnings;
use strict;

my $x = 4;                                                                                                                            
my $y = 1;                                                                                                                            


if ( ! myFunction($x,$y) ) {
    print "myFunction returned false\n";
} else {
    print "myFunction returned true\n";
}

sub myFunction {
    my ($x,$y) = @_;
    my $response;

    if ( $x + $y == 2 ) {
        $response = "fun";
    } else {
        $response = "no fun";
    }
}

This will always print 'myFunction returned true' since either branch of the conditional is technically a true response. However, if you add a return value to the negative branch of the conditional, it will now work:

#!/usr/bin/perl

use warnings;
use strict;

my $x = 4;
my $y = 1;


if ( ! myFunction($x,$y) ) {
    print "myFunction returned false\n";
} else {
    print "myFunction returned true\n";
}

sub myFunction {
    my ($x,$y) = @_;
    my $response;

    if ( $x + $y == 2 ) {
        $response = "fun";
        return 1; # technically not really needed
    } else {
        $response = "no fun";
        return 0;
    }
}

$ perl test_funct.pl
myFunction returned false

Comments

0

You're attempting to call return for your subroutine from inside an eval. This will not perform as you expect as explained in the docs for return:

  • return EXPR
  • return

    Returns from a subroutine, eval, or do FILE with the value given in EXPR. ...

The bug you're facing can be demonstrated in the following example:

sub myFunction {
    eval {
        return "inside eval";
    };

    return "outside eval";
}

print myFunction();

Outputs:

outside eval

To fix your subroutine, assign your return value inside the eval, but actually return it from outside. Also, be sure to localize your alarm signal handler.

sub myFunction {
    my ($run, $runTime) = @_;

    my $code;

    eval {
        local $SIG{ALRM} = sub {die "Operation Timed Out";};
        alarm($run_time);
        $EXIT_STR = `$run`; # Execute $run and save output in EXIT_STR
        alarm(0);
        $code = $?;         # Save cmd exit code.
    };

    if ($@) {
        if ($@ =~ /Operation Timed Out/) { 
            print "Time out\n";
            $code = 10;
        }
    }

    return $code;
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.