New to “Error Handling”

The “Error Handling” chapter is really two chapters: one on dealing with error and warning messages that Perl gives you, and creating those messages on your own for people using your code.

When I first wrote this chapter, Perl’s “exception” handling was poor. We had the basics that we still use, but we hadn’t figured out all of the special cases. Try::Tiny and TryCatch didn’t show up until 2009, about four years later. Not only did I need to cover those important developments, but the background behind them.

autodie also replaced Fatal in core.

In the first edition, I covered Carp in the “Debugging” chapter. I don’t know what I was thinking then, but I’ve moved that to this chapter, leaving a big hole in that chapter; I’ll have to figure out what to do about that, but later.

I also added my ReturnValue discussion. We treat errors and return values as different things; even worse,, we treat them as unstructured data so we need to know special things about every function to know what it’s return value means. Is undef a valid result or an error? What about 0 or the empty string? With a return value object, we can ask directly. I don’t expect anyone to use my module, but the idea of this module.

I think I also avoided the easy trap for a chapter like this: I didn’t make it just a survey of modules. We know from Perl history that best practices and favorite modules have short lifetimes compared to book publishing rates. I hope I gave people enough to think about so they could evaluate future.

You can read this chapter in O’Reilly Atlas.

How I waste my time while writing

I’ve been keeping track of how I spend my time working on Mastering Perl. Most of that time is tracking down bugs in CPAN modules. For instance, to write two paragraphs about TryCatch for the Detecting and Reporting Errors” chapter, I’ve spent about seven hours trying to figure out why this seemingly trivial example doesn’t work (RT #87128 ):

use v5.10.1;
use TryCatch;

try {
	die "This died"
	}
catch {
	say "Caught [$@]";  # $@ is always blank
	}

As usual, I should have started with the RT queue to see if someone had already reported the bug. I found that it was reportedly as part of RT #49072.

This is not a huge problem. If you are using TryCatch, you probably want the advanced features to catch errors by type or you want to specify your own variable:

use v5.10.1;
use TryCatch;

try {
	die bless {}, 'Local::Foo';
	}
catch (Local::Foo $err) {
	say "Caught Local::Foo [$err]";
	}
catch ($err) {
	say "Caught [$err]";
	}

I first tried this on v5.18 and I had trouble installing it as Package::Stash and Package::Stash::XS seemed to have an unmet circular dependency such that I had to force install one of them to get the dependency-heavy TryCatch to install. Since I wanted to test several versions, I had to handle this five times and wait close to an hour for it to install in all versions on my puny laptop. All of that got me no further than reporting the bug to RT.

When I embark on these explorations, I don’t think I’m setting out for an adventure and an answer always seems right around the corner. The solution is always right around the corner and I want to try one more thing; every thing I try makes it more elusive.

I’ve also starting patching some distributions, then realizing they use Dist::Zilla, which means many things aren’t where they will finally show up and I’d have to install a very heavy tool to do very basic things. I’m really sad that people are cutting off so many people from submitting patches; the casual user who isn’t a module maintainer isn’t going to suffer the installation of tools and learning where to find things just to make a quick patch. It’s a couple times a week that I abandon a patch for this reason. I don’t even bother to send the problem to RT because I figure I’ve already wasted enough time, and if I can’t make the patch, I’m disinclined to bother with a report. If I were going to use the module for work, things might be different, but I’m just writing about them.

ReturnValue on PrePAN

As part of the “Error Handling and Reporting” chapter, I’ve developing my use of normal return values to indicate failure. Instead of tricky value checking, I can use the object type to decide what happened and then look in the object to get the value. That way, success and error values can use the same code path. I’ve created ReturnValue on Github.

Before uploading to CPAN, however, I’m trying PrePAN for the first time. This allows me to show off ReturnValue to the Perl community without claiming the namespace. I don’t deal with PAUSE at all. If I decide to abandon it, it’s no big deal. Comment on ReturnValue at PrePAN.

You can also read the draft chapter on O’Reilly Atlas.

New to “Error Handling”

There’s much to update in Chapter 12, “Error Handling”. I thought this would be an easy chapter.

Since v5.10, Fatal is different and now called autodie. I mostly had to change the module names. The biggest change was removing the non-void non-handling of builtins that Fatal could do. If Fatal saw I checked the return value of a builtin myself, it doesn’t throw the exception for me. I excised that paragraph.

In v5.14 the behavior of $@ changes quite a bit. An eval inside a destructor won’t mess up $@ as the scope is cleaning up.

I’m covering Try::Tiny and TryCatch. I’m still working on those sections.

Do you have anything else I should include or update? See what I have so far by reading it through Atlas.