On Wed, 8 Jun 2022 09:04:23 +0200
Alexander Hartmaier <alex.hartmaier@gmail.com> wrote:
> I really wonder that I've never read a blog post or mailing list
> thread about the lack in exception handling in Perl 5. It's my
> biggest pain point with Perl 5 and I'd love to help to improve the
> situation!
Well-volunteered :)
If you want to assist, probably the first main question that needs
answering is working out what the programmer-visible API on these
things ought to be.
While it is initially tempting to suggest that `catch` would expose
core-thrown exceptions as objects, there is already a problem here. In
the past 20-odd years, the $@ variable (and more recently catch) have
always exposed core-thrown exceptions as plain strings; anything that
appears as an object must have been some user-thrown object:
use builtin 'blessed';
try {
maybe_call_a_func();
}
catch ($e) {
if(blessed $e) {
warn "Caught a user-defined exception of type " . (blessed $e);
}
else {
warn "Caught a plain stringy exception";
}
}
What should we do here?
1) Throw objects of some core-defined type, so `ref` and `blessed` are
now true on these things, meaning they can be distinguished -
including by some sort of `isa` test as might someday be added to
`catch`, but thus breaking all existing code which inspects $@ or
$e.
2) Throw plain strings that have some other, new way to query some
hidden "error type" information stored within them. Maybe lets
invent some new `builtin` funcs and imagine a hypothetical future
use builtin 'extype';
...
catch($e) {
my $t = extype $e;
if($t eq "SOMETHING") { ... }
elsif ...
}
Here the model is that $@ or catch would expose "exception values";
things that look and feel like plain strings (and so not upsetting
`ref` or `blessed`, etc...) but nevertheless have extra information
about the exception stored inside them. There's also then temptation
to add other information:
my $errno = exerrno $e; # $!, like ENOENT, EACCESS, ...
my @callers = excallers $e; # each value looking like the result
# of caller()
etc...
Once we have an `extype` that can query on the type string(?) or
other information stored inside an error value, it becomes tempting
to try to get `try`/`catch` in on the action as well:
try { ... }
catch($e extype X::ENOENT) { warn "File missing" }
catch($e extype X::EACCESS) { warn "Access not permitted" }
...
This is partly the reason why `try`/`catch` syntax is still marked
experimental. I still want to save room to add things like this.
The Syntax::Keyword::Try CPAN module already permits `catch` blocks
conditional on object type or stringy regexp match (the latter
simply because of core's existing message strings):
try { ... }
catch($e isa X::SomeExceptionClass) { ... }
catch($e =~ m/^Can't call method ".*" on an undefined value at /) { ... }
It'd be great to have something better than these really fragile
string matches here.
0) Do nothing and leave the situation as it is.
Currently, perl core has taken option 0. I want to change this.
I don't like option 1 because of all the breakage it causes.
I think option 2 could work but it needs a lot more careful design
work, thinking, (pre)RFCs writing, etc...
Do you want to help with that?
--
Paul "LeoNerd" Evans
leonerd@leonerd.org.uk | https://metacpan.org/author/PEVANS
http://www.leonerd.org.uk/ | https://www.tindie.com/stores/leonerd/
Alexander Hartmaier <alex.hartmaier@gmail.com> wrote:
> I really wonder that I've never read a blog post or mailing list
> thread about the lack in exception handling in Perl 5. It's my
> biggest pain point with Perl 5 and I'd love to help to improve the
> situation!
Well-volunteered :)
If you want to assist, probably the first main question that needs
answering is working out what the programmer-visible API on these
things ought to be.
While it is initially tempting to suggest that `catch` would expose
core-thrown exceptions as objects, there is already a problem here. In
the past 20-odd years, the $@ variable (and more recently catch) have
always exposed core-thrown exceptions as plain strings; anything that
appears as an object must have been some user-thrown object:
use builtin 'blessed';
try {
maybe_call_a_func();
}
catch ($e) {
if(blessed $e) {
warn "Caught a user-defined exception of type " . (blessed $e);
}
else {
warn "Caught a plain stringy exception";
}
}
What should we do here?
1) Throw objects of some core-defined type, so `ref` and `blessed` are
now true on these things, meaning they can be distinguished -
including by some sort of `isa` test as might someday be added to
`catch`, but thus breaking all existing code which inspects $@ or
$e.
2) Throw plain strings that have some other, new way to query some
hidden "error type" information stored within them. Maybe lets
invent some new `builtin` funcs and imagine a hypothetical future
use builtin 'extype';
...
catch($e) {
my $t = extype $e;
if($t eq "SOMETHING") { ... }
elsif ...
}
Here the model is that $@ or catch would expose "exception values";
things that look and feel like plain strings (and so not upsetting
`ref` or `blessed`, etc...) but nevertheless have extra information
about the exception stored inside them. There's also then temptation
to add other information:
my $errno = exerrno $e; # $!, like ENOENT, EACCESS, ...
my @callers = excallers $e; # each value looking like the result
# of caller()
etc...
Once we have an `extype` that can query on the type string(?) or
other information stored inside an error value, it becomes tempting
to try to get `try`/`catch` in on the action as well:
try { ... }
catch($e extype X::ENOENT) { warn "File missing" }
catch($e extype X::EACCESS) { warn "Access not permitted" }
...
This is partly the reason why `try`/`catch` syntax is still marked
experimental. I still want to save room to add things like this.
The Syntax::Keyword::Try CPAN module already permits `catch` blocks
conditional on object type or stringy regexp match (the latter
simply because of core's existing message strings):
try { ... }
catch($e isa X::SomeExceptionClass) { ... }
catch($e =~ m/^Can't call method ".*" on an undefined value at /) { ... }
It'd be great to have something better than these really fragile
string matches here.
0) Do nothing and leave the situation as it is.
Currently, perl core has taken option 0. I want to change this.
I don't like option 1 because of all the breakage it causes.
I think option 2 could work but it needs a lot more careful design
work, thinking, (pre)RFCs writing, etc...
Do you want to help with that?
--
Paul "LeoNerd" Evans
leonerd@leonerd.org.uk | https://metacpan.org/author/PEVANS
http://www.leonerd.org.uk/ | https://www.tindie.com/stores/leonerd/