Should 'CATCH' be called strictly after 'throw'?
Example 1:
say 'Hello World!';
class E is Exception { method message() { "Just stop already!" } }
CATCH {
when E {
.resume;
}
}
E.new.throw;
Error:
Cannot find method 'sink': no method cache and no .^find_method in block at /tmp/739536251/main.pl6 line 11
Example 2:
say 'Hello World!';
class E is Exception { method message() { "Just stop already!" } }
E.new.throw;
CATCH {
when E {
.resume;
}
}
No error
You can throw it in your code and catch it in a catch clause. And you can but don't need to specify if your method throws it.
Basically, Java custom exceptions are used to customize the exception according to user needs. In simple words, we can say that a User-Defined Exception or custom exception is creating your own exception class and throwing that exception using the 'throw' keyword.
catch blocks A catch-block will catch a thrown exception if and only if: the thrown exception object is the same as the exception object specified by the catch-block. the thrown exception object is the subtype of the exception object specified by the catch-block.
Generally, you catch many exceptions, generalize them into one and throw it.. So that all similar exceptions can be handled in the same way..
It's an already filed .resume
bug.
The error message isn't the most awesome P6 has ever produced but it isn't technically LTA because it is descriptive and related to the error (caused by the bug).
CATCH and throw in custom exception
I think it's just a .resume
bug rather than being about custom exceptions.
Should 'CATCH' be called strictly after 'throw'?
No, that's not the issue. (That said, putting it after the .throw
just so happens to avoid this bug; I'll return to that later.)
In the code that goes boom, you throw an exception, then .resume
in response to it. Per the doc .resume
:
Resumes control flow where
.throw
left it
Which in this case means where the arrow points:
E.new.throw ;
🡅
Now, consider this program:
42;
If you run that program you'll see:
Useless use of constant integer 42 in sink context (line 1)
That's because Raku applies "sink context" rules when deciding what to do at the end of a statement. Applying sink context entails calling .sink
on the value produced by the statement. And for 42
the .sink
method generates the "useless" warning.
But what's the value of a .resume
d thrown exception?
class E is Exception {}
CATCH { when E { .resume } }
say E.new.throw.^name; # BOOTException
E.new.throw.sink; # Cannot find method 'sink':
# no method cache and no .^find_method
It turns out it's a BOOTException
object which isn't a high level Raku object but instead a low level VM object, one that doesn't have a .sink
method (and also stymies P6's fallback methods for finding a method, hence the "I tried everything" error message).
So why does putting the CATCH
block after the throw make a difference?
It seems the bug only occurs if the throw statement is the last statement. This works fine, just displaying 42
:
class E is Exception {}
CATCH { when E { .resume } }
E.new.throw;
say 42;
As you presumably know, Raku treats the last statement of a block specially. Perhaps this bug is related to that.
CATCH
must be in same block.
Problem in the first example is that no E
but another exceptions is thrown. Try
class E is Exception { method message() { "Just stop already!" } };
CATCH {
when E {
.resume;
}
default { say .perl }
}
E.new.throw;
you could change when
block
class E is Exception { method message() { "Just stop already!" } };
CATCH {
when E {
say .message;
}
}
E.new.throw;
or definition of the class E
, e.g.
class E is Exception {
has $.resume;
method message() { "Just stop already!" }
};
CATCH {
when E {
say .resume;
}
}
E.new(resume => 'stop here').throw;
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With