[% setvar title TITLE %]

This file is part of the Perl 6 Archive

Note: these documents may be out of date. Do not use as reference!

To see what is currently happening visit http://www.perl6.org/

TITLE

Merge $!, $^E, $@ and $?

VERSION

  Maintainer: Peter Scott <peter@psdt.com>
  Date: 25 Aug 2000
  Last Modified: 3 Oct 2000
  Mailing List: perl6-language-errors@perl.org
  Number: 151
  Version: 4
  Status: Frozen

ABSTRACT

The distinction between the $!, $^E, $@ and $? variables is no longer worth trading for the benefits to be gained from merging them together.

DESCRIPTION

The $! variable made excellent sense in Perl 4 as a representation of the Unix C RTL errno. It went right along with the tight integration and close mapping between Perl and sections 2 and 3 of the Unix manual.

The amount of third-party code published via CPAN made possible by the module features of Perl 5, and the likelihood of exception handling gaining increased importance in Perl 6 both serve to make the distinction between errors for which $! is set and those it isn't, less useful.

Non-system code throws exceptions by dieing and any code that handles those exceptions reads the reasons in the $@ variable. Why have two classes of errors where failure reasons are passed in different variables when the distinction between those classes may appear irrelevant (not a Unix platform) or arbitrary (what is a "system error" and why should it be set for a failed open but not, say, for a failed new IO::Socket?)?

Hence this proposal is to merge all these together into a single out-of-band indicator of error, so that users don't have to check multiple variables in the case of an eval.

IMPLEMENTATION

Merge all these variables into one. Say for the sake of argument that it is $! (for the mnemonic value of "something went bang"). This variable will always be an object. An attribute will determine whether it is something that can be caught or could cause a die; this will be checked by code implementing exception handling (like, say, RFC 88). Call this attribute is_exception for the sake of argument.

It should be possible to make the same attribute fulfil and extend the requirement of RFC 70 to make Fatal.pm applicable throughout the core and optionally to user modules.

Note that if RFC 88 passes, it requires $@ to become a structured object anyway; this RFC simply proposes using the same object for other errors as well.

What about situations where more than one of the current set of four variables might be set? Well, note that $^E is just an extension of $!, so we can consider those two variables collapsed into $!. The following cases obtain:

    Perl would    |    The error variable is currently
    currently set |Non-existent: |Existent, and is_exception is
                  |create new one|    true      |    false
                  |setting its   |              |
                  |is_exception  |              |
    ==============|==============|==============|===============
        $!, $^E   | Depends on   | Overwrite,   |
                  | Fatal.pm     | but see      |
                  | applicability| discussion   |  Overwrite
    --------------+--------------+ below        |
         $?       | False        |              |
    --------------+--------------+--------------+---------------
         $@       | True         | New one links| New one links
                  |              | to previous  | to previous
                  |              | per RFC 88   | via sysmsg

The one case that needs special attention is (assuming RFC 88 passes) when the variable is holding a current exception and a non-exception error occurs. Furthermore, the only place this is a problem is catch and finally blocks (see RFC 88). It cannot occur in a try block because as soon as anything would create an exception, it will cause control to leave the try block.

In a catch block, the exception is to be cleared at the end of the block anyway so overwriting it with a non-exception error would not cause a problem for control flow. In a finally block, any current exception needs to be preserved at the end of the block, therefore it cannot be overwritten; but Perl could save the exception on entry to the finally block and restore it on exit. The one remaining issue is how the user can access the current exception in a catch or finally block after a non-exception error. In this arguably rare case, they could get it from the first element of the @@ array, which RFC 88 defines as the exception stack.

To expand upon parts of the above table:

After a failed system, `` or anything else that currently sets $?: the variable will be created with the is_exception attribute false. In a numeric or string context, the variable will be the number that would currently be placed in $?. If the variable already existed, then if is_exception was false, it is overwritten, otherwise see the discussion above.

On a failed system call (something that currently sets $!; not a system call): the variable will be created with the is_exception attribute false. The value of the variable in numeric and string contexts will be the same as what would currently be placed in $!. Where the $^E variable would currently be set, set a extra_info attribute or some such. (We could actually use the sysmsg attribute, but that might confuse people traversing linked errors who expect that always to be a reference or undef.) If the variable already existed, then if is_exception was false, it is overwritten, otherwise see the discussion above.

On a throw or die: the variable will be created with the is_exception attribute true. If the variable previously existed with a is_exception value of false, a link to the previous value will be provided in the sysmsg attribute. RFC 88 details how and under what circumstances the variable is linked to a previous version which had is_exception true.

Impact on RFC 88

If the variable chosen is $@, no impact. If the variable chosen is $!, then $@ needs to be changed to $!. The implementation of RFC 88 will need to check not merely for the existence of the error variable but whether its is_exception attribute is set to know whether there is a current exception.

REFERENCES

"Error Indicators" in perlvar

RFC 88: Structured Exception Handling Mechanism (Try)

RFC 80: Exception objects and classes for builtins

RFC 70: Allow exception-based error reporting