Provided by: libsyntax-keyword-try-perl_0.26-1build1_amd64 bug

NAME

       "Syntax::Keyword::Try" - a "try/catch/finally" syntax for perl

SYNOPSIS

          use Syntax::Keyword::Try;

          sub foo {
             try {
                attempt_a_thing();
                return "success";
             }
             catch ($e) {
                warn "It failed - $e";
                return "failure";
             }
          }

DESCRIPTION

       This module provides a syntax plugin that implements exception-handling semantics in a form familiar to
       users of other languages, being built on a block labeled with the "try" keyword, followed by at least one
       of a "catch" or "finally" block.

       As well as providing a handy syntax for this useful behaviour, this module also serves to contain a
       number of code examples for how to implement parser plugins and manipulate optrees to provide new syntax
       and behaviours for perl code.

       Syntax similar to this module has now been added to core perl, starting at version 5.34.0. If you are
       writing new code, it is suggested that you instead use the Feature::Compat::Try module instead, as that
       will enable the core feature on those supported perl versions, falling back to "Syntax::Keyword::Try" on
       older perls.

Experimental Features

       Some of the features of this module are currently marked as experimental. They will provoke warnings in
       the "experimental" category, unless silenced.

       You can silence this with "no warnings 'experimental'" but then that will silence every experimental
       warning, which may hide others unintentionally. For a more fine-grained approach you can instead use the
       import line for this module to only silence this module's warnings selectively:

          use Syntax::Keyword::Try qw( try :experimental(typed) );

          use Syntax::Keyword::Try qw( try :experimental );  # all of the above

       Don't forget to import the main "try" symbol itself, to activate the syntax.

KEYWORDS

   try
          try {
             STATEMENTS...
          }
          ...

       A "try" statement provides the main body of code that will be invoked, and must be followed by either a
       "catch" statement, a "finally" statement, or both.

       Execution of the "try" statement itself begins from the block given to the statement and continues until
       either it throws an exception, or completes successfully by reaching the end of the block. What will
       happen next depends on the presence of a "catch" or "finally" statement immediately following it.

       The body of a "try {}" block may contain a "return" expression. If executed, such an expression will
       cause the entire containing function to return with the value provided. This is different from a plain
       "eval {}" block, in which circumstance only the "eval" itself would return, not the entire function.

       The body of a "try {}" block may contain loop control expressions ("redo", "next", "last") which will
       have their usual effect on any loops that the "try {}" block is contained by.

       The parsing rules for the set of statements (the "try" block and its associated "catch" and "finally")
       are such that they are parsed as a self- contained statement. Because of this, there is no need to end
       with a terminating semicolon.

       Even though it parses as a statement and not an expression, a "try" block can still yield a value if it
       appears as the final statement in its containing "sub" or "do" block. For example:

          my $result = do {
             try { attempt_func() }
             catch ($e) { "Fallback Value" }
          };

       Note (especially to users of Try::Tiny and similar) that the "try {}" block itself does not necessarily
       stop exceptions thrown inside it from propagating outside. It is the presence of a later "catch {}" block
       which causes this to happen. A "try" with only a "finally" and no "catch" will still propagate exceptions
       up to callers as normal.

   catch
          ...
          catch ($var) {
             STATEMENTS...
          }

       or

          ...
          catch {
             STATEMENTS...
          }

       A "catch" statement provides a block of code to the preceding "try" statement that will be invoked in the
       case that the main block of code throws an exception. Optionally a new lexical variable can be provided
       to store the exception in. If not provided, the "catch" block can inspect the raised exception by looking
       in $@ instead.

       Presence of this "catch" statement causes any exception thrown by the preceding "try" block to be non-
       fatal to the surrounding code. If the "catch" block wishes to optionally handle some exceptions but not
       others, it can re-raise it (or another exception) by calling "die" in the usual manner.

       As with "try", the body of a "catch {}" block may also contain a "return" expression, which as before,
       has its usual meaning, causing the entire containing function to return with the given value. The body
       may also contain loop control expressions ("redo", "next" or "last") which also have their usual effect.

       If a "catch" statement is not given, then any exceptions raised by the "try" block are raised to the
       caller in the usual way.

   catch (Typed)
          ...
          catch ($var isa Class) { ... }

          ...
          catch ($var =~ m/^Regexp match/) { ... }

       Experimental; since version 0.15.

       Optionally, multiple catch statements can be provided, where each block is given a guarding condition, to
       control whether or not it will catch particular exception values. Use of this syntax will provoke an
       "experimental" category warning on supporting perl versions, unless silenced by importing the
       ":experimental(typed)" tag (see above).

       Two kinds of condition are supported:

       •

              catch ($var isa Class)

           The  block  is  invoked  only if the caught exception is a blessed object, and derives from the given
           package name.

           On Perl version 5.32 onwards, this condition test is implemented using the same op type that the core
           "$var isa Class" syntax is provided by and works in exactly the same way.

           On older perl versions it is emulated by a compatibility function. Currently this function  does  not
           respect a "->isa" method overload on the exception instance. Usually this should not be a problem, as
           exception class types rarely provide such a method.

       •

              catch ($var =~ m/regexp/)

           The block is invoked only if the caught exception is a string that matches the given regexp.

       When  an exception is caught, each condition is tested in the order they are written in, until a matching
       case is found. If such a case is found the corresponding block is invoked, and no  further  condition  is
       tested.  If  no contional block matched and there is a default (unconditional) block at the end then that
       is invoked instead. If no such block exists, then the exception is propagated up to the calling scope.

   finally
          ...
          finally {
             STATEMENTS...
          }

       A "finally" statement provides a block of code to the preceding "try"  statement  (or  "try/catch"  pair)
       which  is  executed  afterwards,  both in the case of a normal execution or a thrown exception. This code
       block may be used to provide whatever clean-up operations might be required by preceding code.

       Because it is executed during a stack  cleanup  operation,  a  "finally  {}"  block  may  not  cause  the
       containing  function  to  return,  or  to alter the return value of it. It also cannot see the containing
       function's @_ arguments array (though as it is block scoped within the  function,  it  will  continue  to
       share  any  normal  lexical  variables declared up until that point). It is protected from disturbing the
       value of $@. If the "finally {}" block code throws an exception, this will be printed as  a  warning  and
       discarded, leaving $@ containing the original exception, if one existed.

       Note that the "finally" syntax is not available when using this module via Feature::Compat::Try, as it is
       not  expected  that  syntax will be added to the core perl 'try' feature. This is because a more general-
       purpose ability may be added instead, under the name 'defer'. If you wish to write  code  that  may  more
       easily  be forward-compatible with that feature instead, you should consider using Syntax::Keyword::Defer
       rather than using "finally" statements.

OTHER MODULES

       There are already quite a number of modules on CPAN that provide a "try/catch"-like syntax for Perl.

       • Try

       • TryCatch

       • Try::Tiny

       • Syntax::Feature::Try

       In addition, core perl itself gained a "try/catch" syntax based on this module at version 5.34.0.  It  is
       available as "use feature 'try'".

       They are compared here, by feature:

   True syntax plugin
       Like  Try  and  Syntax::Feature::Try,  this module is implemented as a true syntax plugin, allowing it to
       provide new parsing rules not available to  simple  functions.  Most  notably  here  it  means  that  the
       resulting combination does not need to end in a semicolon.

       The core "feature 'try'" is also implemented as true native syntax in the perl parser.

       In  comparison,  Try::Tiny  is plain perl and provides its functionality using regular perl functions; as
       such its syntax requires the trailing semicolon.

       TryCatch is a hybrid that uses Devel::Declare to parse the syntax tree.

   @_ in a try or catch block
       Because the "try" and "catch" block code is contained in a true block rather  than  an  entire  anonymous
       subroutine,  invoking  it  does  not  interfere with the @_ arguments array. Code inside these blocks can
       interact with the containing function's array as before.

       This feature is unique among these modules; none of the others listed have this ability.

       The core "feature 'try'" also behaves in this manner.

   "return" in a try or catch block
       Like TryCatch and Syntax::Feature::Try, the "return" statement has its usual effect within  a  subroutine
       containing syntax provided by this module.  Namely, it causes the containing "sub" itself to return.

       It also behaves this way using the core "feature 'try'".

       In comparison, using Try or Try::Tiny mean that a "return" statement will only exit from the "try" block.

   "next"/"last"/"redo" in a try or catch block
       The  loop  control keywords of "next", "last" and "redo" have their usual effect on dynamically contained
       loops.

       These also work fine when using the core "feature 'try'".

       Syntax::Feature::Try documents that these do not work there. The other modules make no  statement  either
       way.

   Value Semantics
       Like  Try  and  Syntax::Feature::Try,  the  syntax  provided  by this module only works as a syntax-level
       statement and not an expression. You cannot assign from the result of a "try" block. A common  workaround
       is  to wrap the "try/catch" statement inside a "do" block, where its final expression can be captured and
       used as a value.

       The same "do" block wrapping also works for the core "feature 'try'".

       In comparison, the behaviour implemented by Try::Tiny can  be  used  as  a  valued  expression,  such  as
       assigned to a variable or returned to the caller of its containing function.

   "try" without "catch"
       Like Syntax::Feature::Try, the syntax provided by this module allows a "try" block to be followed by only
       a  "finally"  block,  with no "catch". In this case, exceptions thrown by code contained by the "try" are
       not suppressed, instead they propagate as normal to callers. This matches the behaviour familiar to  Java
       or C++ programmers.

       In  comparison, the code provided by Try and Try::Tiny always suppress exception propagation even without
       an actual "catch" block.

       The TryCatch module does not allow a "try" block not followed by "catch".

       The core "feature 'try'" does not implement "finally" at all, and also requires that every "try" block be
       followed by a "catch".

   Typed "catch"
       Try and Try::Tiny make no attempt to perform any kind of typed dispatch to distinguish kinds of exception
       caught by "catch" blocks.

       Likewise the core "feature 'try'" currently does not provide this ability, though it remains an  area  of
       ongoing design work.

       TryCatch  and  Syntax::Feature::Try  both  attempt  to  provide  a kind of typed dispatch where different
       classes of exception are caught by different blocks of code, or propagated up entirely to callers.

       This module provides such an ability, via the currently-experimental "catch (VAR cond...)" syntax.

       The design thoughts continue on the RT ticket <https://rt.cpan.org/Ticket/Display.html?id=123918>.

WITH OTHER MODULES

   Future::AsyncAwait
       As of "Future::AsyncAwait" version 0.10 and Syntax::Keyword::Try version 0.07,  cross-module  integration
       tests  assert  that  basic  "try/catch" blocks inside an "async sub" work correctly, including those that
       attempt to "return" from inside "try".

          use Future::AsyncAwait;
          use Syntax::Keyword::Try;

          async sub attempt
          {
             try {
                await func();
                return "success";
             }
             catch {
                return "failed";
             }
          }

ISSUES

   Thread-safety at load time cannot be assured before perl 5.16
       On perl versions 5.16 and above this module is thread-safe.

       On perl version 5.14 this module is thread-safe provided that it is "use"d before any additional  threads
       are created.

       However,  when using 5.14 there is a race condition if this module is loaded late in the program startup,
       after additional threads have been created. This leads to the potential for it to be started up  multiple
       times  concurrently,  which  creates  data races when modifying internal structures and likely leads to a
       segmentation fault, either during load or soon after when more code is compiled.

       As a workaround, for any such program that creates multiple  threads,  loads  additional  code  (such  as
       dynamically-discovered plugins), and has to run on 5.14, it should make sure to

          use Syntax::Keyword::Try;

       early on in startup, before it spins out any additional threads.

       (See also <https://rt.cpan.org/Public/Bug/Display.html?id=123547>)

   $@ is not local'ised by "try do" before perl 5.24
       On perl versions 5.24 and above, or when using only control-flow statement syntax, $@ is always correctly
       "local"ised.

       However,  when  using  the experimental value-yielding expression version "try do {...}" on perl versions
       5.22 or older, the "local"isation of $@ does not correctly apply around the  expression.  After  such  an
       expression,  the  value  of  $@  will  leak  out if a failure happened and the "catch" block was invoked,
       overwriting any previous value that was visible there.

       (See also <https://rt.cpan.org/Public/Bug/Display.html?id=124366>)

ACKNOWLEDGEMENTS

       With thanks to "Zefram", "ilmari" and others from "irc.perl.org/#p5p" for assisting with trickier bits of
       XS logic.

AUTHOR

       Paul Evans <leonerd@leonerd.org.uk>

perl v5.34.0                                       2022-02-06                          Syntax::Keyword::Try(3pm)