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

Hello,
I have a subroutine in which I make several calls to different subroutines. Each call has this syntax:
$error_msg = sub1(); return $error_msg if ($error_msg ne ()); $error_msg = sub2(); return $error_msg if ($error_msg ne ());
and so on several times.

In these routines (sub1, sub2..) I have returns with messages if anything goes wrong. Otherwise I end with return ();
Is there a way I can avoid to check after each call the content of $error_msg, in order to return to the caller, and have it "implicitly" present in the subroutine ?

Thank you,
Roberto

Replies are listed 'Best First'.
Re: Managing errors in subroutines
by Bilbo (Pilgrim) on Apr 16, 2003 at 09:48 UTC

    Well, you could do something like this:

    sub test_sub { my $error_msg = sub1() || sub2() || sub3(); return $error_msg; }

    This works because (quoting from perlop) "Binary "||" performs a short-circuit logical OR operation. That is, if the left operand is true, the right operand is not even evaluated", so $error_msg will contain the first non-zero return value or zero if all subs are successful, and no more subroutines are called after one has returned a non-zero value.

    Of course, if your program does other things between each subroutine call then this won't help.

      Yes, I forgot to specify that here are many other instructions between them. However, thank you for your comment.
      Roberto
Re: Managing errors in subroutines
by zby (Vicar) on Apr 16, 2003 at 09:54 UTC
    Is there a way I can avoid to check after each call the content of $error_msg, in order to return to the caller, and have it "implicitly" present in the subroutine ? - yes with exeptions. For example you can use Error or Exception modules for this. Recently there was some discussion here about error handling in general: Error reporting in modules, How to say 'oops' in OOPs?.
Re: Managing errors in subroutines
by Joost (Canon) on Apr 16, 2003 at 15:37 UTC
    I would probably go about this differently:
    # starting point sub start { eval { call1(); call2(); }; return 0 if $@; return 1; } sub call1 { # code here die "Error in call1" if $something_nasty; call3(); # more code } sub call2 { # code here die "Error in call2" if $something_nasty; # more code here.. } sub call3 { # code here die "Error in call3" if $something_nasty; # more code here.. }

    In other words use die and eval BLOCK to trow and catch exceptions, and you won't have to check every subroutine call, just catch the error at the place you want to process it.

    See the die and eval entries in perlfunc for more info.

    -- Joost downtime n. The period during which a system is error-free and immune from user input.
Re: Managing errors in subroutines
by godzirra (Acolyte) on Apr 16, 2003 at 12:14 UTC
    You could always just have your sub routines return 1 or 0 and set a param with the error message, and then instead of this:

    $error_msg = sub1();
    return $error_msg if ($error_msg ne ());

    you can do this:

    return $error_param if not sub1();

    Godzirra!
    Destroying Neo Tokyo since 1954

      It's possible to do better than that. Remember Perl's notions of truth can be applied to more than just numeric values. Just return "" if there's no error (which evaluates to false), and return whatever error string is appropriate otherwise, which will evaluate to true.
Re: Managing errors in subroutines
by rupesh (Hermit) on Apr 16, 2003 at 10:03 UTC
    Listen,
    If in case you were to do something after each subroutine, and the procedure depends on the value of the error_msg, then you would have to do the checking as you are currently doing...
    Otherwise, you could check the status in each sub routine and exit in case false...
    Even bilbo's suggestion seems cool..
Re: Managing errors in subroutines
by shotgunefx (Parson) on Apr 16, 2003 at 20:51 UTC
    You could always use falsified error messages.

    -Lee

    "To be civilized is to deny one's nature."