Both this and Rob's article seem to be hiding an inefficiency: if one of the early functions in the chain (hint) fails, the rest of them are still called, just to do nothing. It also hinders understandability and debugging, since you're continually bombarded with "if(err)" after the first failure.
I've thought about this problem too (error handling in general), and with that hint of this being a "chain", arrived at this solution which I think is extremely concise and elegant:
if((err = func1()) ||
(err = func2()) ||
(err = func3()) ||
(err = func4()) ||
...
) {
/* handle the error */
}
or if you want to get more fancy and know which step failed, int step = 0;
if((step++, err = func1()) ||
(step++, err = func2()) ||
(step++, err = func3()) ||
(step++, err = func4())
) {
...
Of course this can be modified suitably if your error vs. success values are different, but the structure is the same: a chain of actions one after another, broken only by short-circuit evaluation. It's surprising that this pattern isn't seen more, because I've shown this to a few others and the response has almost always been an initial puzzlement followed by "wow, that's extremely neat" or "why didn't I think of that?" This is certainly an example of "use the language".