The Stringceptional Difficulty of Changing Error Messages


Perl 5.10 modified a warning message in a wonderful and useful way. If you've used Perl 5 much at all, you've accidentally stringified an undefined value. If you enable warnings, you've seen the message Use of uninitialized value....

In Perl 5.10, that message changed to include the name of the uninitialized variable when it's available. This was a huge usability improvement and it's one of my favorite features of modern Perl. Sometimes changing a warning or error message for user clarity is the kindest improvement ever.

(Having an interactive shell react to the user typing exit with the message Type Ctrl-D to exit! is a response to user confusion in the wrong direction.)

Unfortunately, changing error and warning messages in Perl 5 is a quagmire because parsing unstructured data is a mess. Want to catch an exception in Perl 5? You can do it safely with a module such as Try::Tiny, but to find out what the exception is, you have to perform string manipulations on $@.

If you're performing an exact match, a substring match, or a regular expression, any change to the text of that message in a subsequent release of Perl 5 could change the way your code behaves. Thus p5p must be very, very, very careful about even improving the text of internal exceptions and warnings, lest they break the DarkPAN.

The only real solution in Perl 5 is never to attempt to parse the text of exceptions and to consider throwing exception objects with something like Exception::Class. Adding true exception object support to the Perl 5 core in a backwards-compatible fashion is also very possible, though that's a subject for another post.


Would it make sense to ship core perl with a module that can automatically parse these messages into modules? The addition of the variable would only result in the addition of a field to that package, module authors could continue to use an interface like this:

  eval { 
    local $SIG{__DIE__} = sub { 
      my $exception = Exception->PromotePerlException(@_);
      unless($exception->isa('Exception::Perl::UninitializedValue')) { 
            # rethrow object, $obj stringifies to traditional message
            # PromotePerlException will detect this and simply
            # return the same reference.
            die $obj;

Using Exception::Class in Bricolage also allowed us to internationalise our error messages. The code (and tests) checked what class of exception we were getting, but the text was locale-sensitive. It's a feature that not enough people appreciate.

Modern Perl: The Book

cover image for Modern Perl: the book

The best Perl Programmers read Modern Perl: The Book.

sponsored by the How to Make a Smoothie guide



About this Entry

This page contains a single entry by chromatic published on August 6, 2010 11:47 AM.

The Memory Optimization That Almost Wasn't was the previous entry in this blog.

Improving Perl 5's Core Exceptions is the next entry in this blog.

Find recent content on the main index or look in the archives to find all content.

Powered by the Perl programming language

what is programming?