I posted about this subject on Stack Overflow yesterday[1], but I chose a
poor example of something that raises an exception (dividing by zero, which
apparently doesn't necessarily do so) on which the answers have mostly
focused.

I was looking for a way to evaluate an expression, and if the expression
threw an exception, for a default value to be provided instead.  For
example, in Ruby:

    quotient = begin; a / b; rescue; -1; end

Or in Lisp:

    (setq quotient (condition-case nil (/ a b) (error -1)))

Not having written much exception-related code in Perl 6, I hoped that this
might work:

    sub divide($a, $b) { die "Zero denominator" if $b == 0; $a / $b }
    my $quotient = do { divide($a, $b); CATCH { default { -1 } } };

It doesn't, though.  As far as I can tell, the value to which a CATCH block
evaluates is ignored; the only useful things one can do in such a block are
things with side effects.  Long story short, I eventually came up with this:

    my $quotient = do { my $q; { $q = divide($a, $b); CATCH { default { $q
= -1 } } }; $q };

That's far more verbose than I've come to expect from Perl 6.  Is there
some more concise way of expressing this logic?

The doc page on exceptions mentions try, eg:

    my $quotient = try { divide($a, $b) } // -1;

That works in this specific case, but it seems insufficient in general.
The function might validly return an undefined value, and this construction
can't distinguish between that and an exception.  Also, it wouldn't let me
distinguish among various exception cases.  I'd have to do something like:

    class EA is Exception { }
    class EB is Exception { }
    sub divide($a, $b) { (EA, EB).pick.new.throw if $b == 0; $a / $b }

    my $quotient = do { my $q; { $q = divide($a, $b); CATCH { when EA { $q
= -1 }; when EB { $q = -2 } } }; $q };


[1]
https://stackoverflow.com/questions/51644197/returning-values-from-exception-handlers-in-perl-6/51670573

Reply via email to