-
Notifications
You must be signed in to change notification settings - Fork 560
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[feature] Firstclass exception type representation #17951
Comments
As part of the 5.31 series we bumped the bit representation of SV types in order to allocate some more. We went from 15 possible with 14 used, up to 31 possible - so we now have plenty of free ones. I would therefore like to suggest we allocate a new one, for now codenamed EV, to contain a native "error value". In terms of interface to interact with it, there are a lot of questions. A lot of what follows is now just some random top-of-my-head ideas; I'm quite sure they won't be the final form of whatever idea this turns into, but serves just as a starting point for further discussion.
try { ... }
catch ($e) {
return if $e->type eq "invocant::undef";
warn sprintf "Caught an exception of type %s in file %s line %d.\n",
$e->type, $e->file, $e->line;
warn $e->message;
} Any code not aware that these are objects with some methods, and instead just sees them as plain unblessed strings in the "traditional perl" sense of them, would continue to get plain message strings out of them. unless( eval { ...; 1 } ) {
warn "Oopsie, it failed $@"; # normal stringification
}
try { ... }
catch ($e) {
return if $e->type eq "invocant::undef" and $e->methodname eq "do_thing";
...
}
ref($e) eq undef; # looks like a string
reftype($e) eq "ERROR"; # but reftype knows different
As they are not blessed refs into some package, I would suggest they can never be
I would suggest a third kind of try { ... }
catch ($e errtype invocant::undef) {
return if $e->methodname eq "do_thing";
...
}
Currently most code that wants to throw a plain string exception does so either with sub f {
throw "It is not Tuesday today", type => "runtime::not_tuesday;
} |
On 7/7/20 10:15 AM, Paul Evans wrote:
As part of the 5.33 series we bumped the bit representation of SV types
It should have read 5.31 series
|
Why not avoid using words like weird? Some people feel good enough about eval {}, and I am one of them. |
Instead of creating a new thing that behaves like an object, why not just use an object? To deal with legacy code that expects string exceptions for perl thrown exceptions maybe we could add a new feature, say "stringify_exceptions" that like the indirect feature defaults on. When the following holds:
Perl calls that method for the value for If exceptions are rethrown from code with the feature enabled they'll lose their object-ness, but this allows us (and downstream) to at least incrementally update code to support object exceptions for perl generated exceptions. Using a new method instead of just overloading The perl exception objects would likely also overload Another option would be to just start throwing objects (that overload |
This would be hugely useful; right now, for example, when a module fails to load we have to parse the string to determine if the failure is because of nonexistence of the module or invalidity of the parsed code. It would be much safer for us to have typed errors instead. What is the advantage to designating a new SV type (EV) versus harnessing Perl’s existing object mechanism? I note that, while CPAN contains an “Exception.pm” module, it’s just a placeholder; maybe core could take that over and do something good with it?
For consistency with the existing PROPAGATE method, perhaps STRINGIFY instead? |
Currently different SV types mean having a different memory layout. What are the requirements for different internal representation of your proposal, why can't it be satisfied with an existing SV type? |
Actually I have implemented a full try-catch block in a module on CPAN: Nice::Try using perl filters. It enables embedded try-catch blocks, return, variable assignments, no need for semicolon on the last brace and more. So you can do something like:
Full disclosure: I have developed this module when TryCatch got broken due to the discontinuation of Devel::Declare. |
I brought this, because I thought it would be helpful in response to the earlier comment:
Nice::Try tries to implement closely the try-catch block as seen in other languages and this includes catching object exceptions like: Excellent news this is now handled at the core! |
Note that core's implementation lacks |
Fear not; that's what Currently CPAN expermental; a little too late to have got into 5.34, but hopefully 5.36. |
@leonerd |
It is not clear from the announcement of addition to perl's core that the try-catch block can handle multiple catch blocks based on exception class. For example:
|
@jackdeguest I think core try/catch isn’t class-aware yet. |
Indeed. Given the time constraints to get something into 5.33 before the feature freeze ahead of 5.34's release, I opted to go with a minimum-viable product of just the single, untyped There is definitely space to expand on that design once we open for feature development again in 5.35 - I definitely hope to bring more of the features from Syntax::Keyword::Try into core - such as the typed catch. |
As part of my ongoing thoughts about a core try/catch syntax, I have been thinking more about the plain string exceptions that core perl throws. It continues to feel weird when designing a nice
try/catch
with typed dispsatch, that all core exceptions are only plain strings.It would be nice, for the purposes of typed catch, if we could somehow distinguish different types of core-thrown exception, so as not to have to have such ugly string matching as
With some native type attached to these exceptions we could do other fun things like asking the file/line/package/etc.. of where they were thrown from too.
As usual with these design cases we can often start by looking at CPAN for inspiration, but as usual all of CPAN necessarily comes upon the limitation of what is currently possible in Perl. They all fall short here, because any of the exception type systems on CPAN by necessity have to be implemented as some sort of blessed object, and thus
becomes true; whereas this has always been false for a core-thrown stringy exception type. I feel that if we want to have better
information around exceptions in core perl we need to be careful not to break the vast amount of existing code which is expecting this condition to hold.
(this also posted to perl5-porters@ as https://www.nntp.perl.org/group/perl.perl5.porters/2020/07/msg257948.html)
The text was updated successfully, but these errors were encountered: