Beefy Boxes and Bandwidth Generously Provided by pair Networks
The stupid question is the question not asked
 
PerlMonks  

Croak, return et al.

by packetstormer (Monk)
on Aug 16, 2014 at 15:39 UTC ( [id://1097676]=perlquestion: print w/replies, xml ) Need Help??

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

Hello Monks

I have a 'best practice' query. Suppose the simple script below. I want to (or maybe I don't!) create a module that might fail under certain circumstances. However, I would like to continue on from the calling script. I realise I could use 'return' but then I'd have to catch that value

So, with that in mind does anyone have any thoughts on how the package below might be rewritten to allow the calling script continue? I could also just print "SPLAT";return but I am unsure what the norm is.
You can see that I could use eval (commented out) but again, I am unsure of the best practice!?

#!/usr/bin/perl use strict; use Data::Dumper; my @r = (1..5); foreach (@r) { print "Start for $_\n"; my $splat = Splat->new(); #eval { $splat->splat() }; #if ($@) {next} if ($_ ==1) { print "Never getting this far\n" } } print "Nor this far\n"; package Splat; use Carp qw(croak); sub new { my $class = shift; my $self = {}; bless $self,$class; return $self; } sub splat { my $self = shift; croak "SPLAT!" if ! $self->{splat} } 1;

Replies are listed 'Best First'.
Re: Croak, return et al.
by McA (Priest) on Aug 16, 2014 at 16:07 UTC

    Hi,

    the most important part is to document that your module/class/object may throw an exception and to explain under what condition this happens. In my opinion there are two main classes of exceptions: Runtime exceptions which are most of the time not recoverable (but probably sometimes with a retry) and exceptions caused by a module usage which is not allowed. I'm not a friend of an exception being a regular "output" of a method/function.

    So, my (absolute personal) rule of thumb is: When you use a function/method in the intended way in a "working" runtime environment you shouldn't get an exception.

    In your case: When you know as a caller of the class that you often will run into an exception situation it is valid to wrap all with an eval (better Try::Tiny) or check the invalid usage before calling the function/method.

    Regards
    McA

      Thanks for the replies! It seems to confirm there isn't any fixed way but there is plenty for me to run with.

Re: Croak, return et al.
by AppleFritter (Vicar) on Aug 16, 2014 at 16:04 UTC

    You can see that I could use eval (commented out) but again, I am unsure of the best practice!?

    That's how I'd do it: die (or croak) in your module if necessary, and have the caller wrap the call in question in an eval to catch the exception (since that's what it really is).

    Of course this can get cumbersome, so if your subroutine can only return certain values (e.g. only values that are true), you could also return false or undef, and have the caller invoke it like this:

    $splat->splat() or die "splat() returned false"; unless(defined $splat->splat()) { die "splat() returned undef"; }

    (Hmm, it sure would be nice if perl had a defined-or version of the or operator.)

    Whether this is feasible depends on what splat() is supposed to be return, of course. For numbers there's a trick: you can return a string along the lines of "0 but true"; this'll numify to zero, but evaluate to true in boolean contexts. For strings, I don't think there's any such trick for the empty string.

    There is no single best solution; it's a matter of taste.

      For numbers there's a trick: you can return a string along the lines of "0 but true"; this'll numify to zero, but evaluate to true in boolean contexts. For strings, I don't think there's any such trick for the empty string.

      That's the semi-predicate problem. If a function is supposed to return a string, which may be empty without this being an error, and may also have to return failure, one way to make the distinction is to return a reference to the string rather than the string itself (a reference will always be true even is the string is empty) and undef when the function fails.

      I had to do something similar recently where a function had to return an array (and returning an empty array was not supposed to be an error). I just decided to return a reference to the array or undef when the input was exhausted (failure). This way I could distinguish between the three different cases and act accordingly

        Oh, that's clever! I'll have to remember that.
Re: Croak, return et al.
by Anonymous Monk on Aug 16, 2014 at 20:22 UTC

    Here's a recent thread with a very similar question and helpful replies: Using die() in methods

    APIs where methods return a false value to indicate error are very common in Perl and many other languages, leaving the error handling up to the user. In this case, I might base my decision on how often you expect the error condition to occur - if often, then return;, if not, then die.

    Note that your use of $@ is not completely reliable; what would be better is eval { $splat->splat(); 1 } or next; (see e.g. "Background" in Try::Tiny).

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://1097676]
Approved by ww
Front-paged by ww
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others chilling in the Monastery: (5)
As of 2024-03-29 13:08 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found