Tuesday, 9 February 2010

catch...from

A brief post off my usual JavaScript track for a digression into Java and related languages (although come to think of it, the concept below applies just as much to JavaScript as Java).

Exception handling features in languages are fantastic. They let us (if we're careful and thorough) express the mainline logic of our code uninterrupted by the niggly little detail that just about anything can fail at just about any time, and then let us handle those failures in clearly-defined "...and if that goes wrong, do this" blocks. In pseudocode:

try
{
doThis();
doThat();
doTheOther();
return result;
}
catch (ExceptionalCondition ec)
{
// Handle it
}
Lovely and wonderful. We were able to express what we're really trying to do (this, that, and the other) clearly, but then handle the fact that this, that, or the other can fail. The equivalent in, say, C would be to use the convention that returning 0 means everything was fine and returning !0 means something went wrong:
if (doThis() == 0)
{
if (doThat() == 0)
{
if (doTheOther() == 0)
{
return result;
}
}
}
// Handle the fact that something failed
(Although you probably wouldn't write it quite like that.)

So for obvious reasons I'm a big fan of exception constructs, but there's a refinement I've been wanting for a good 10+ years now (maybe it's about time I got around to submitting a JSR or something; they don't seem to be getting my telepathic messages):

catch..from

This is probably best expressed with an example:
FileOutputStream    output;
Socket socket;
InputStream input;
byte[] buffer;
int count;

// Not shown: Opening the input and output, allocating the buffer,
// getting the socket's input stream

try
{
while (/* ... */)
{
count = input.read(buffer, 0, buffer.length);
output.write(buffer, 0, count);

// ...
}
}
catch (IOException ioe from input)
{
// Handle the error reading the socket
}
catch (IOException ioe from output)
{
// Handle the error writing to the file
}
As you can see, the goal here is to separate the logic that handles errors reading from the socket from the completely unrelated logic that handles errors writing to the file.

A very basic idea, but I've never heard of anyone implementing it. This may be because I'm so shockingly brilliant that no one else has ever thought of this. (A kind reader will not immediately consider the converse argument.) Or, more likely, there are a lot of subtleties involved that make it tricky.

For instance, exceptions thrown by other objects being used under-the-covers by the socket or file output stream instance need to be handled as though thrown by the socket or output stream instance once they get to the level where we've caught them. But that shouldn't be that hard, although it would require that the stack trace record instance information.

Another wrinkle comes from checked exceptions: Does my code above throw IOException, or not? I've caught it if it's thrown by input or output, and those are the only two instances I've used methods on that may throw the exception, so no, my code doesn't throw IOException. But it'll require enhancing compilers so they can figure that out. But that, too, doesn't seem that complicated.

It's very hard to do the above (in a general way) without language support, hence the suggestion that it may be worth adding a construct to the language.

Happy coding.

No comments: