develooper Front page | perl.perl5.porters | Postings from July 2020

Firstclass exception type representation

Thread Next
From:
Paul "LeoNerd" Evans
Date:
July 7, 2020 16:16
Subject:
Firstclass exception type representation
Message ID:
20200707171637.35f808ae@shy.leonerd.org.uk
TL;DR - I would like a real representation of "exception" types


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

  try { $maybeobj->do_thing }
  catch ($e) {
    return if $e =~ m/^Can't call method \"do_thing\" on an undefined
  value /;
  }

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

  ref $@

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.


As part of the 5.33 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.


 *) Does it act like an object, with accessor methods?

    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
    }

 *) If it does so, there is much scope for one day trying to define
    some more specific fields to store more information about certain
    kinds of exception:

    try { ... }
    catch ($e) {
      return if $e->type eq "invocant::undef" and $e->methodname eq
    "do_thing";
      ...
    }

 *) What do `ref` or `reftype` make of these new things? For the best
    combination of back-compat + usefulness I can first think that

      ref($e) eq undef;       # looks like a string
      reftype($e) eq "ERROR"; # but reftype knows different

 *) What does the newly-added `isa` operator think of them?

    As they are not blessed refs into some package, I would suggest
    they can never be `isa` anything.

 *) What does my proposed `catch TYPE` syntax think of them?

    I would suggest a third kind of `catch` syntax that can see them:

    try { ... }
    catch ($e errtype invocant::undef) {
      return if $e->methodname eq "do_thing";
      ...
    }

 *) How can modules throw these things?

    Currently most code that wants to throw a plain string exception
    does so either with `die` or `croak`. There's relatively little use
    of a toplevel function called `throw`, even around existing
    exception code, so it suggests we could add a new `throw` which can
    create one of these, perhaps annotated with other information.

    sub f {
      throw "It is not Tuesday today", type => "runtime::not_tuesday;
    }



This idea is cross-posted to github at
  https://github.com/Perl/perl5/issues/17951

-- 
Paul "LeoNerd" Evans

leonerd@leonerd.org.uk      |  https://metacpan.org/author/PEVANS
http://www.leonerd.org.uk/  |  https://www.tindie.com/stores/leonerd/

Thread Next


nntp.perl.org: Perl Programming lists via nntp and http.
Comments to Ask Bjørn Hansen at ask@perl.org | Group listing | About