I think the reason programmers in C/C++/Java style languages have been attracted to exceptions is simply because the syntax does not have a concise way to call a function that returns multiple values, so it’s hard to write a function that either produces a return value or returns an error.
Funny enough, looking back at the first Python link, the equivalent code using exceptions is often longer than the code that doesn’t.
Thankfully, derive4j alleviates pain by employing annotation processing to generate a significant amount of code on our behalf like Google’s AutoValue. In fact, we can somewhat emulate Rust’s Result and Haskell’s Either with only a few lines of code:
The resulting class generated by derive4j is 200 lines, so not a bad tradeoff!
Here’s an example of parsing a CSV using jackson-csv using a bit of validation in the same vein that javaslang does validation.
Here RuntimeJsonMappingException is an unchecked exception that I didn’t realize could be thrown until after several tests. The underlying library shouldn’t determine what is exceptional, as what I’ve found is that one person’s exception is one person’s normal input (think CSV linter).
The Result can be used as follows:
So not too terrible, but we start running up against the limits of the Java language with conciseness.
Let’s try our program on some inputs. First the happy path:
A CSV file that contains a row that is too long
Trying to load a nonexistant file:
A CSV file with too many issues to count
Exceptions are useful, but I believe that the programmer should be the only person to determine where exceptions are raised and caught. Haskell has exceptions, Rust and Go have panics, so it’s not as if one has to live without exceptions, but one should live with minimal exceptions.
I find it funny that Go specifically says that “failing to open a file [is not] exceptional”, but I’d say that if I have a file watcher and it handed me a file, I’d be surprised if the file didn’t exist. Thus APIs should give the caller all the necessary information in a return value.