http://www.perlmonks.org?node_id=309692

In Java, it's easy to know how try { } catch { } block line up by using simple indentation rules:

try { // Do Stuff } catch (IOException e) { // Handle IO errors } catch (Exception e) { // Handle any other error }

The equivilent construct in Perl (without using modules) is to use an eval { }:

eval { # Do stuff }; if($@) { # Handle any errors }

The problem is that it isn't immediately apparent that the if block is equivilent to a Java catch (i.e., something that catches errors, as opposed to one of the infinate number of other uses for an if statement). To a novice Perl coder, it's just an if statement with a weird punctuation variable in the conditional. Even an experianced Perl coder needs to read more information to know what it does, since the Human brain tends to read an entire word at a time.

One could use the Exception Error module (Update: I meant Error.pm here. Thanks Zed_Lopez.), but that module has issues with its implementation and should probably be avoided.

The next best solution that I'm putting forth is to break normal indentation rules:

eval { # Do stuff }; if(@$) { # Handle any errors }

By cuddling the if, and being consistant in not cuddling anywhere else (you are being consistant, right?), you're saying "this if statement is related to the eval above it". To a novice, it still has a weird punctuation variable next to it, but at least they're hinted in as to its true function. To an experianced one, they can recognize the construct without extra intepretation at the HumanOS layer.

----
I wanted to explore how Perl's closures can be manipulated, and ended up creating an object system by accident.
-- Schemer

: () { :|:& };:

Note: All code is untested, unless otherwise stated

Replies are listed 'Best First'.
Re: Style Point: Catching eval { } errors
by diotalevi (Canon) on Nov 24, 2003 at 21:23 UTC

    Even better, don't depend on $@.

    eval { # Do stuff 1; } or do { # Handle errors };

    I commonly write this to bring in $@ without being obfuscatory.

    eval { ... ; 1} or die "Barfoo ... $@";
      I don't remember seeing any reference to this in the documentation for eval. If their were I would have used it.

      Perhaps it should be there? It seems to me that eval {} or do {} is the perfect idiom for using eval with exceptions.

        perldoc -q eval
        In both forms (eval EXPR / eval BLOCK), the value returned is the value of the last expression evaluated inside the mini-program; a return statement may be also used, just as with subroutines. The expression providing the return value is evaluated in void, scalar, or list context, depending on the context of the eval itself. See "wantarray" for more on how the evaluation context can be determined.
Re: Style Point: Catching eval { } errors
by Abigail-II (Bishop) on Nov 24, 2003 at 22:26 UTC
    Considering that Perl came first, shouldn't Java programmers adapt their style to make Perl programmers feel home?

    Abigail

      Good ideas can come from otherwise crappy languages. I think Java-style exception handling was a really good idea that Perl can almost (but not quite) do without using modules. With modules like Exception, you can get 90% of what Java has. You can get closer with Error, but it has other problems.

      ----
      I wanted to explore how Perl's closures can be manipulated, and ended up creating an object system by accident.
      -- Schemer

      : () { :|:& };:

      Note: All code is untested, unless otherwise stated

        You mentioned Error.pm having problems a couple of times - can you be a bit more specific about the particulars of these problems?

        I find myself using Error.pm quite a bit in web applications, and would be quite interested to know.

        You can get closer with Error, but it has other problems.

        Given than Exception uses closures like Error I doubt it doesn't have these "other" problems too. The main problem is that currently the only way to add try/catch syntax to Perl without core changes it is to use closures what may cause memory leaks if you are not careful.

        --
        Ilya Martynov, ilya@iponweb.net
        CTO IPonWEB (UK) Ltd
        Quality Perl Programming and Unix Support UK managed @ offshore prices - http://www.iponweb.net
        Personal website - http://martynov.org

Re: Style Point: Catching eval { } errors
by etcshadow (Priest) on Nov 25, 2003 at 06:30 UTC
    I don't know... I tend to think of that as just a perlism. I'd argue that even an intermediate perl programmer ought to know about $@, and ought to expect to see it fluttering around evals. Ultimately, yes, it may be "punctuation"y, but so are regular expressions. So are hashes. So is much of what makes perl perl. I don't think that a programming language has to be wordy to be understandable.

    How are some of these other things written in Java? (Forgive me for probably getting some of the class/method names wrong, but structurally, this is what it's like):

    $string =~ s/this/that/ig; --- RegEx re = new RegEx(/this/i); string = string.replace(re,"that","g");
    or hashes:
    %hash = ( foo => 'bar', ferd => 'snodgrass', ); $hash{thing}; --- HashTable hash = new HashTable(); hash.add("foo", "bar"); hash.add("ferd", "snodgrass"); hash.lookup("thing");
    So the Java way is, in general, more wordy and less full of punctuation (well, maybe not by volume of punctuation characters, but, at the very least, the punctuation is more mundane).

    Don't get me wrong, I'm not being critical of the Java way... I'm just saying that it is different from the Perl way, and that there isn't anything wrong with that.


    ------------
    :Wq
    Not an editor command: Wq
Re: Style Point: Catching eval { } errors
by Zed_Lopez (Chaplain) on Nov 25, 2003 at 00:43 UTC

      Actually, I meant Error. I get the two confused sometimes.

      ----
      I wanted to explore how Perl's closures can be manipulated, and ended up creating an object system by accident.
      -- Schemer

      : () { :|:& };:

      Note: All code is untested, unless otherwise stated

Re: Style Point: Catching eval { } errors
by bsb (Priest) on Nov 25, 2003 at 07:34 UTC
    I tried another approach here Exception catching sub.
    It doesn't fit your example as is but could be easily tweaked.

    TIMTOWTDI

Re: Style Point: Catching eval { } errors
by Aristotle (Chancellor) on Nov 26, 2003 at 11:58 UTC
    You can even get creative:
    if(eval { # Do stuff }, $@) { # Handle any errors }
    :-)

    Makeshifts last the longest.

      If you want to be creative, and can actually stand the function prototypes, you can do this:
      sub try (&@) { my($code, $error_handler) = @_; eval { $code->(); }; $error_handler->() if $@; } sub catch (&) { return @_; }
      The & allows you to pass code blocks directly without the sub keyword. You can then write:
      my $msg; try { open (FILE, "strangefilename") || die "$!"; $msg = <FILE>; } catch { print "File could not be opened because of: $@\n"; $msg = "BAAAAH"; }
      This code is from the perlsub perldoc page.
        This is what Exception lets you do, and unfortunately has numerous problems. The simplest gotcha of all - did you notice your last snippet is missing a semicolon?

        Makeshifts last the longest.

Re: Style Point: Catching eval { } errors
by Beechbone (Friar) on Nov 27, 2003 at 03:21 UTC
    I defined for our current project that exception handlers must be written as:
    eval { # Do stuff }; if (my $e = $@) { # Handle any errors }
    This brings the commonly used "e" into the game. I think this makes it more obvious what's happening here.

    Ok, in this project it gets even easier:

    eval { # Do stuff }; if (my $e = $@) { unless (UNIVERSAL::isa($e, 'Our::Project::Exception')) { $e = Our::Project::Exception::ThirdPartyError->new($e); } # Handle any errors }

    Search, Ask, Know