On Wednesday, May 18, 2016 11:40 PM, Brandon Allbery wrote:
On Wed, May 18, 2016 at 11:29 AM, Brandon Allbery <allber...@gmail.com <mailto:allber...@gmail.com>> wrote:

    On Wed, May 18, 2016 at 11:27 AM, mt1957 <mt1...@gmail.com
    <mailto:mt1...@gmail.com>> wrote:

        This has something to do with lazy evaluation. It triggers the
        calculation when it wants to show the value in $r.


    IIRC it doesn't throw, it returns a Failure (deferred/lazy
    exception that throws when accessed).


And, since this does not seem to be documented in obvious places yet: "use fatal;" pragma changes these lazy exceptions to strict ones.
"use fatal;" does not change the behaviour. The Failure is only thrown when referred to. But if the reference is outside the block that contains the CATCH block to trap the error, then the error is not caught.
The problem is something like:

{ #some code ...
    { # block with error prone code
        # Failure created
        # no statement like 'say' to get the failure thrown
        CATCH { # code to trap error
        }
    } # end of block with error prone code
    # more code
    say .... ; # code that causes the Failure to throw an exception
}

Since the exception is thrown outside the block with the CATCH block, it is not caught.

How can the lazy / deferred Failure be trapped?

A suggestion:
Would it be possible to implement a C( try ) block so that it forces all Failures to throw Exceptions that can be caught in the CATCH?

If it is necessary to have blocks with an explicit CATCH to have deferred exceptions, then this behaviour could be kept for ordinary blocks, whilst try blocks force the exception.

For the code I was originally working on, which was for arithmetic expressions, a work around is to coerce to Num. But it seems to me this is not a general solution.

use fatal;
my $r;
for 0..4 -> $s {
   try {
     $r = 5 / (3 - $s);
     CATCH {
       when X::Numeric::DivideByZero { $r = 65 }
       default { $r = 55 }
     }
    }
    say "At line $?LINE r is $r";
}
## results in
At line 11 r is 1.666667
At line 11 r is 2.5
At line 11 r is 5
Attempt to divide 5 by zero using div
  in block <unit> at test.pl line 11

Actually thrown at:
  in block <unit> at test.pl line 11

### But
my $r;
for 0..4 -> $s {
     $r = (5 / (3 - $s)).Num;
    say "At line $?LINE r is $r";
}
#### results in
At line 4 r is 1.66666666666667
At line 4 r is 2.5
At line 4 r is 5
At line 4 r is Inf
At line 4 r is -5

Reply via email to