Java Reference
In-Depth Information
In the functional world, you only have two options for handling a situation: you will deal with it either
upon input or upon output. If you are dealing with exceptional circumstances in a functional world, this
means that you are either going to be passing exception handlers as an argument, or you will be passing
information about exception occurrences as part of the return value. Working with exceptions this way
may seem strange, but that is simply the experience of learning a new paradigm. This way of working with
exceptions may also seem complicated, but the reality is that it is handling the complication intrinsic in I/O.
The difference between engineers and artists is that engineers are punished for ignoring the real world.
Throughout the rest of this chapter, we will begin with a simple task: working with a temporary file. We
will see where the exceptions arise, and work with both input and output styles of handling them. Then we
will build our more advanced file systems from there. So let's get started.
Temporary Files and the Hole in the Middle
In the first chapter, we saw how inversion of control was an object-oriented way of performing a functional
callback. There's a common pattern in the functional world where a function performs some setup at the
beginning, some cleanup at the end, and then calls back into the user code to figure out what to do in the
middle. My friend, mentor, and co-blogger, Brian Hurt, refers to this as the “hole in the middle” pattern.
When dealing with temporary files, that's exactly what we want: we want to create the temporary file at the
start, and we want to ensure the temporary file is cleaned up at the end, and allow the users to do what they
would like with the file in the middle. The basic pattern will look like this:
<RETURN_T> RETURN_T withTempFile(Function<FunFile, RETURN_T> function) {
File file = null;
try {
file = File.createTempFile("funfile", "tmp");
return function.apply(file);
} finally {
if (file != null) file.delete();
}
}
// This is not valid Java code: read on!
The setup of the temporary file is our File.createTempFile(String,String) call. The cleanup is the
file.delete() call. The function.apply call is the hole in the middle, which the caller will fill in for us. But,
of course, this is not valid Java code: there is the unhandled IOException that needs to be addressed. As we
discussed previously, we have two options: handling the exception on input via a callback, and handing the
exception on output via the return value. Let's take a look at both of these approaches in turn.
Exception Handling via Input: Passing in an Exception Handler
If you take a look at the basic pattern above, you can actually think of it as having two holes in the middle:
one that is the standard behavior, and one that is the exceptional behavior. Therefore, you could take two
callbacks: one implementing the standard behavior, and one implementing the exceptional behavior.
A naïve implementation would look like this:
<RETURN_T> RETURN_T withTempFile(
Function<FunFile, RETURN_T> function,
Consumer<IOException> exceptionHandler
) {
 
Search WWH ::




Custom Search