The square root of 5 is 2.23606797749979
The square root of 0 is 0
Cannot take square root of -3: negative
Other error: Nominal type check failed for parameter '$x'; expected Real but got Complex instead

A few interesting points: the presence of a CATCH block automatically makes the surrounding block catch exceptions. Inside the CATCH block, all lexical variables from the outside are normally accessible, so all the interesting information is available for error processing.

Inside the CATCH block, the error object is available in the $_ variable, on the outside it is available in $!. If an exception is thrown inside a CATCH block, it is not caught — unless there is a second, inner CATCH that handles it.

The insides of a CATCH block typically consists of when clauses, and sometimes a default clause. If any of those matches the error object, the error is considered to be handled. If no clause matches (and no default block is present), the exception is rethrown.

Comparing the output from rakudo to the one that niecza produces for the same code, one can see that the last line differs:

This higlights a problem in the current state: The wording of error messages is not yet specified, and thus differs among implementations.

I am working on rectifying that situation, and also throwing interesting types of error objects. In the past week, I have managed to start throwing specific error objects from within the Rakudo compiler. Here is an example:

The string that is passed to EVAL is not a valid Perl 6 program, because it accesses an attribute that wasn’t declared in class A. The exception thrown is of type X::Attribute::Undeclared, and it contains several details: the name of the attribute, the type of package it was missing in (could be class, module, grammar and maybe others), the name of the package, the actual error message and information about the source of the error (line, cfile name (empty because EVAL() operates on a string, not on a file), and column, though column isn’t set to a useful value yet).

X::Attribute::Undeclared inherits from type X::Comp, which is the common superclass for all compile time errors. Once all compile time errors in Rakudo are switched to X::Comp objects, one will be able to check if errors were produced at run time or at compile with code like

So Perl 6 has a rather flexible error handling mechanism, and libraries and applications can choose to throw error objects with rich information. The plan is to have the Perl 6 compilers throw such easily introspectable error objects too, and at the same time unify their error messages.

Many thanks go to Ian Hague and The Perl Foundation for funding my work on exceptions.

Like this:

LikeLoading...

Related

This entry was posted on December 15, 2011 at 12:39 pm and is filed under 2011. You can follow any responses to this entry through the RSS 2.0 feed.
You can leave a response, or trackback from your own site.

X is just a namespace in which exceptions go by default, but it’s not mandatory to put them there.

There is currently no type constraint for what you can throw. die "some string" and die 404 both work, but the mechanism that catches the exceptions will wrap them into an object of type Exception, which provides the backtrace and other meta data. I’m not sure yet if that exact mechanism is here to stay, but we will continue to allow the user throw exceptions without first writing classes for it.

I get the feeling that it’s considered OK to have “stringly typed” exception handling, for example smart-matching on error messages and the supposed need for standardized messages. Is it not better to standardize exception subclasses and let the message be free-form? It might still be human-friendly to standardize the messages but surely it’s more programming-friendly to match against classes/types?

Perl follows the TIMTOWDI principle; it’s ok for the user to throw string errors; it’s not OK for the compiler. And exception types are what you should be matching against, yes

But even if we standardize the exception types, we need to unify the wording of the error messages, because there will be non-Perl 6 tools with which we interact. For example if you log the output from a Perl 6 application, and then change the compiler you use under the hood, it would be nice if the wording of the error messages didn’t change, so that the log analyzer doesn’t think a new class of errors occured.