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

Dear Monks

I've been playing with the try/catch example from Prototypes, but although the tutorial seems clear, I can't figure out why my test code doesn't work:
#! /usr/bin/perl -l sub try (&@) { my($try,$catch) = @_; eval { &$try }; if ($@) { local $_ = $@; &$catch; } } sub catch (&) { $_[0] } try { die "phooey"; } catch { /phooey/ and print "unphooey\n"; }; # my test code catch { print "unphooey again\n"; } ; __END__ output: unphooey
Any suggestion why it doesn't print "unphooey again" ?

cheers
LuCa

Replies are listed 'Best First'.
Re: pass code block to function (PROTOTYPES)
by JavaFan (Canon) on Jul 15, 2009 at 10:20 UTC
    Because all catch does is return the block. It doesn't call the code. The code is called from try, and then only when the first block fails.
      that makes a lot of sense!
      I have now fix it as follows:
      #! /usr/bin/perl use strict ; use warnings ; sub try (&@) { my($try,$catch) = @_; eval { &$try }; if ($@) { $catch; } } sub catch (&) { &{$_[0]} } try { die "phooey"; } catch { print "unphooey\n"; }; catch { print "test\n"; } ;
      thnx!
        That doesn't make any sense. Now the argument of catch will be executed even before try is called. You've broken the entire reason of having a try/catch system.

        Why do you want to call catch directly anyway? It's like calling else without an if, or a continue without a while.

Re: pass code block to function (PROTOTYPES)
by LanX (Saint) on Jul 15, 2009 at 14:26 UTC
    The misunderstanding
    # my test code catch { print "unphooey again\n"; } ;

    Sorry, this doesn't make sense! Your completely misunderstanding the aim of catch(), it's basically syntactic sugar, the logic is in try().

    You can also write

    try {... some code to try ... } sub { ... some code to catch }
    for absolutely the same functionality, but writing "catch" instead of "sub" makes the use of try() clearer.

    UPDATE: the use of sub instead of catch is even better, since it allows a a prototype sub try (&&) which catches syntax errors at compile-time. (ATM the second argument to try() isn't necessarily a coderef!)

    Some background
    The deeper underlying "problem" (or asymmetry) in perl is that prototypes distinguish code blocks according to the position in argument list:

    An & requires an anonymous subroutine, which, if passed as the first argument, does not require the sub keyword or a subsequent comma.
    (IMHO to avoid misparsing of literal hashrefs)

    so passing a code reference as a second argument requires an explicit "sub" or just something mimicking a sub like this "catch()" function.

    Bad perldoc
    What I really don't like about this perldoc example is that the prototype of try sub try (&@) is misleading, since it accepts an unlimited list of arguments!

    sub try (&$) would be much better for avoiding false uses and for better intrinsic documentation.

    Where can I report improvements to perldoc?

    Cheers Rolf

      Preferrably as patches (for example via git format-patch), as mail to perl5-porters@perl.org, or via the perlbug utility, which will send the mail for you. perlrepository (alternatively http://perl5.git.perl.org/perl.git/blob/HEAD:/pod/perlrepository.pod) has more information on how to set up a git mirror of bleadperl and how to format a patch but the basic workflow is:

      1. git clone http://perl5.git.perl.org/perl.git bleadperl
      2. Modify the document you want to modify, in your case, perlsub in pod/perlsub.pod
      3. Commit your change(s) by using git commit -a -m "Make perlsub please LanX" or, better, a more descriptive name.
      4. Create a patch file by using git format-patch origin - this should leave you with one (or more) files 0001-make-perlsub-please-lanx.patch, 0002-...
      5. Send these to perl5-porters@perl.org, preferrably with a second description of your rationale behind creating the patch, and what the patch changes.
Re: pass code block to function (PROTOTYPES)
by Corion (Patriarch) on Jul 15, 2009 at 10:10 UTC

    Because your catch { ... } block doesn't reraise the exception.