On 18-02-2012 21:36, H. S. Teoh wrote:
On Sat, Feb 18, 2012 at 08:20:23PM +0100, deadalnix wrote:
[...]
However, in D, I think this is more the role of an Errors. Exception
are something « softer ». It will alert you on problems your program
encounter, but that are recoverable.
I agree.
[...]
Let's get an exemple : your program ask a file to the user and do some
operations with this file. If the file doesn't exists, you can prompt
for another file to the user with a meaningful message and start
again. However, the first version of your program can just ignore that
case and fail with a less specific handler in firsts versions.
You cannot achieve something like that if you don't have a useful
type to rely on. Here something like FileNotFoundException is what
you want.
Exactly. It's important to distinguish between exceptions sometimes.
For example:
File promptSaveFile() {
do {
string filename = readInput();
try {
return File(filename);
} catch(FileNotFoundException e) {
writeln("No such file, please try "
"again");
}
} while(true);
assert(false);
}
It would not make sense for that catch to be *any* Exception; for
example, if the exception was ReadFailureException, you do *not* want to
catch that, but you want to propagate it.
But sometimes, you *want* to handle ReadFailureException, for example:
void salvageBadSector(out ubyte[] sector) {
int n_attempts = 10;
while(n_attempts> 0) {
try {
disk.read(sector);
} catch(ReadFailureException e) {
disk.recalibrate();
n_attempts--;
continue; // try again
}
// If another error occurs, say OutOfMemory,
// or some other unexpected problems, you do NOT
// want to continue.
}
writeln("Cannot salvage data from bad sector");
}
Having distinct exception types allows you to do this without resorting
to hacks, or bypassing the library altogether (because of the use of
overly generic exception types).
Having a proper exception class hierarchy is also necessary. For
example, most programs don't care about the difference between
FileNotFoundException and ReadFailureException; they just want to print
an error message and cleanup if I/O fails:
Data loadData() {
try {
return readFromFile();
} catch(IOException e) {
writeln("I/O error occurred, aborting");
cleanup();
exit(1);
}
assert(false);
}
It would be wrong to just catch Exception here, because if it wasn't an
I/O error, but something else, it needs to be propagated!
The type of the exception must depend on the problem you are facing,
not on the module that trhow it. I see a lot of people doing the «
MyProgramException » or « MyLibException » but that doesn't make
sense. In this case, you are just making things harder.
Agreed.
[...]
If this politic is choosen, then It would make sense to have several
modules of phobos throwing exceptions of the same type, or inheriting
from the same base class.
Phobos NEEDS to have a sane exception hierarchy. ESPECIALLY since it is
the standard library. So you cannot assume your users cares or don't
care about distinguishing between exception types. Some applications
just catch Exception, cleanup and exit, but other applications need to
know the difference between FileNotFoundException and
ReadErrorException.
So we need to design a good exception hierarchy for Phobos.
The worst thing is if Phobos exceptions are too generic, then
applications that need to tell between different problems will have to
bypass Phobos and hack their own solution. Which is not good. The
standard library should be maximally useful to the extent that it can
be.
I'd just like to add to this that we don't lose anything per se by
introducing specific exception types. People can still catch Exception
if they really, really want.
Exception type is a convenient way to filter what you catch and what
you don't know how to handle at this point.
Agreed.
T
--
- Alex