CATCH and throw in custom exception
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;
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 P6 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 P6 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, P6 treats the last statement of a block specially. Perhaps this bug is related to that.