develooper Front page | perl.perl5.porters | Postings from October 2021

Pre-RFC: try/catch/finally and generic finally blocks

Thread Next
Paul "LeoNerd" Evans
October 19, 2021 18:25
Pre-RFC: try/catch/finally and generic finally blocks
Message ID:
In perl 5.34, I implemented a small subset of the full
Syntax::Keyword::Try syntax, being just try/catch, with no finally and
no typed catches.

In perl 5.35.x (I forget which one) we now have `defer` blocks.

Using the same internals that makes them work it would be quite easy to
add the oft-requested try/catch/finally syntax:

  try {
    say "This happens first";
  catch ($e) {
    say "Oops, a failure happened";
  finally {
    say "This always happens, regardless of success or failure";

A try/catch/finally can be implemented basically the same way as if it
was written

    defer { "finally" code goes here }

    try {} catch($e) ... here as normal

I have to admit, that even though SKT allows one to write simply
try/finally with no catch, I have never really liked it. The trouble
with it is that as soon as the reader sees the word "try" they might
feel that this is nicely safe code, where any exceptions will be caught
and handled elsewhere. Only when they scroll down, possibly a long way,
and see the *lack of* catch, will they notice it isn't so safe.

  try {
    ## 100 lines here
  finally {
    say "Oh and just do this before you go"

For that reason, I'm not sure I want to allow simply try/finally
without a catch.

However, many people like the "later code is written lower down" part
of try/finally. It reads somewhat backwards to see the defer {} block
before the main code:

  defer { say "This happens second"; }
  say "This happens first";

I wonder therefore about relaxing the syntax a bit to say that
actually, any bare block or a try/catch pair can be followed by a
`finally` block. Thus, we wouldn't write try/finally, but we could write

    ## 100 lines here
  finally {
    say "Oh and just do this before you go"

There was no `try` at the top, meaning the reader didn't get lulled
into a false sense of security by thinking there's exception-catching
going on here when there isn't. It's just a bare block, doing what bare
blocks do.

Speaking of do, perhaps you'd also permit

  my $result = do { CODE HERE } finally { finish with this };

But that invites questions about value-semantics that I'm not too happy
about asking of what is essentially a control-flow syntax.

As a possible further extension, it could be worth thinking about
whether other kinds of blocks could also permit a trailing `finally` on
them. At the moment I don't have any strong feelings either way, though
offhand I can't immediately imagine what would be the semantics in other

  foreach my $i ( 1 .. 10 ) {
    say $i;
  finally {
    say "Done";

  while( $count-- ) {
    say "Nearly...";
  finally {
    say "Go!";

  if( $x )    { ... }
  elsif( $y ) { ... }
  else        { ... }
  finally     { say "When does this happen?" }

I don't think we should try too hard to give these meanings, as it's
rather unclear what they should do. Likely those should continue to be
syntax errors for now, and we just focus on the bare-block and
try/catch cases. At least for now.

If there doesn't turn out to be a clear consensus on how to proceed, I
probably won't bother adding anything at this stage. After all, these
postfixed "finally" blocks are really just a different spelling of
things that can already be achieved right now with `defer`; all it does
is moves the order of the lines in the source code so they read better
in top-to-bottom temporal order, and lets you get rid of a single set
of braces. It's a small syntax neatening but nothing truely

Thoughts anyone?

Paul "LeoNerd" Evans      |  |

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