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

Re: Thoughts in the direction of a core try/catch syntax

Thread Previous | Thread Next
Paul "LeoNerd" Evans
March 13, 2020 10:31
Re: Thoughts in the direction of a core try/catch syntax
Message ID:
On Sat, 7 Mar 2020 18:47:46 +0100
Leon Timmermans <> wrote:

> Ideally, the error dispatch would be able to re-use a dumber
> smartmatch like the one Paul other topic.
> This rather sounds like a killing two birds with one stone kind of
> situation.

I thought that for a long time. In fact my own documentation in
Syntax::Keyword::Try wrote

  The author considers the lack of such ability in this module to be a
  feature. That kind of dispatch on type matching of a controlling
  expression is too useful a behaviour to be constrained to exception
  catching. If the language is to provide such a facility, it should be
  more universally applicable as a stand-alone independent ability.

However, my observation of the success of Switch::Plain and my thoughts
on a dumb-match point me in the opposite direction now. In 99% of all
realworld cases involving a typed dispatch, one entire dispatch block
provides one *single* comparison operator - maybe string equality,
numerical equality, class derivation, regexp pattern match (eq, ==,
isa, =~). The neatness of dumb-match is that the programmer specifies
which kind of match is being used in this instance at the point of the
`switch`-like place, not the individual `case`s.

Exceptional dispatch in Perl5 has grown up to be a really annoying
hybrid of core strings and user-provided classes. At any given catch
point you might have to deal with a few different exception type classes
*and* a few given core internal string patterns at the same time. This
means a given set of catch blocks must handle *both* isa and =~ in the
same place. It must therefore use a syntax at which the individual
`case`-style labels clearly and unambiguously describe what comparison
semantics are in effect for that one case, rather than for the
`switch`-like block as a whole.

I also vote that for reasons of implementation efficiency and programmer
sanity, it must be *statically* determined which is which. I would not
like to reason upon the runtime semantics were it determined by dynamic
type analysis of case values:

  my $regexp_on_tuesdays = (localtime)[6]==2 ? qr/^Unhandled /
                                             : "X::Unhandled";

  try { func() }
  catch my $e ($regexp_on_tuesdays) { # what does this match?

My next obvious thought was, now we have the `isa` operator, it can
easily be spelled out like an if() condition:

  try { ... }
  catch ($@ isa X::Unhandled)  { uses class derivation test }
  catch ($@ =~ m/^Unhandled /) { uses string regexp pattern match }

This syntax looks nice but doesn't gel nicely with my other syntax
idea, which assigns the exception into a new lexical thus avoiding the
fragile nature of global $@:

  try { ... }
  catch my $e { ... }

Simply combined, the programmer has to specify $e twice in a redundant

  catch my $e ($e isa Oopsie) { ... }

A final thought is if we consider the contents of the parens not as a
generic condition expression but instead as a very limited "only this
syntax allowed" then we could perhaps contemplate allowing

  catch (my $e isa Oopsie) { ... }

but that feels a bit awkward; introducing a new variable as part of a
binary comparison operator yet expecting it to have value; internally
its semantics operate like

  if((my $e = $@) isa Oopsie) { ... }

To be clear here: the syntax is the only real sticking point here. If
we can nail that down, then the semantics of the operation ought to be
fairly obvious from there and I can get on and finish implementing the

Further thoughts on RT at

Paul "LeoNerd" Evans      |  |

Thread Previous | Thread Next Perl Programming lists via nntp and http.
Comments to Ask Bjørn Hansen at | Group listing | About