bzar
A Commando
(I put this here to pandora development to first get a more limited view from the people Iäve dealt with more here. If this warrants further discussion, this thread should be moved somewhere else)
I'll get straight to the point. I want a new programming language level structure which allows me to deal with special cases in calling functions. Current solutions in most languages are return values or exceptions. In my opinion, return values should be just that, return values. They should be reserved to returning expected information relevant to the program logic eg. what the function should return. Exceptions on the other hand should be reserved to operation-scope exceptional situatuations. This leaves us function-level special cases. Zero divisors. Element not found. Consider this (very) simple example (please, no nitpicking over non-relevat things like syntax):
Found the potential hazard? Yes, if d=0, the function reaches a special case, where the division cannot be performed. This is something that should be addressed by the caller and checked by the function. Why checked by the function? Because only the function programmer actually knows what it needs. A typical solution is to use the return value to convey success information:
How about if the function reach any number of special cases like this? Usually that means defining an enumeration data type to list all the possible special cases and switch-casing between them. This again is error-prone, defines a lot of values only used with one function and still makes return value to signify a special case. This, in my opinion is not good.
How about exceptions? They were made to handle special cases that require some special actions? No. In my opinion exceptions should be used in situations where a whole operation can fail a number of ways. Exceptions should be thrown when the programmer feels they are necessary, not when a library programmer does so. This is because a llibrary programmer can not quantify an operation in the program, and as such cannot generate exceptions relevat to that program logic. The program above could be written with exceptions something like this:
Good news: we now have return values dedicated to return values. Bad news: this is a needlessly heavy framework for something as simple as special cases in functions. Exceptions are a nice concept with some good uses, but it really does not fit here. These kind of special cases should be taken into account no matter what, and they are only relevat right where the function is called. Knowing somewhere down the line that somewhere someone divided by zero is not something anyone can handle in any smart way. The only place where thet can be addressed is right where the function is called. In my opinion, exceptions should always be related to the program's concepts. Consider the following example:
Now if the database query function throws an exception QueryFailed, the caller may know that some query failed somewhere. This, again, is not something that can be handled in any smart way. This is why it is a good practice to define program-specific exceptions to translate generic errors to something related to the program's concepts.
See what happened? The database layer gets no actual benefit from using exceptions.
In my opinion, special cases should be handled differently. Both of the approaches above have their merits, but both attempt to make something that does not suit handling special cases into something that does. I propose something like this:
or
The custom exception is still thrown, because not finding a book is not something the caller may need to address. It is not a special case, it is an exception.
This could be handled compile-time, because special cases must be handled right after the function call. In my opinion these special cases should be defined as such, that the programmer should address them immediately no matter what. Not making a handler for a defined special case would raise at least a compiler warning. No more gazillions of small exceptions, try-catches, one-function enum return value definitions, and such.
Let me say, after trying to explain this idea to some of my friends over IRC some people asked what this gives over exceptions. I hope I got myself over better here. I really do think there is something to this idea.
I'll get straight to the point. I want a new programming language level structure which allows me to deal with special cases in calling functions. Current solutions in most languages are return values or exceptions. In my opinion, return values should be just that, return values. They should be reserved to returning expected information relevant to the program logic eg. what the function should return. Exceptions on the other hand should be reserved to operation-scope exceptional situatuations. This leaves us function-level special cases. Zero divisors. Element not found. Consider this (very) simple example (please, no nitpicking over non-relevat things like syntax):
Code:
float div(float n, float d) {
return n/d;
}
int main() {
...
z = div(x, y);
...
return 0;
}
Found the potential hazard? Yes, if d=0, the function reaches a special case, where the division cannot be performed. This is something that should be addressed by the caller and checked by the function. Why checked by the function? Because only the function programmer actually knows what it needs. A typical solution is to use the return value to convey success information:
Code:
bool div(float n, float d, float& result) {
if(d==0) return false;
result = n/d;
return true;
}
int main() {
...
if(!div(x, y, z)) {
(error handling)
}
...
return 0;
}
How about if the function reach any number of special cases like this? Usually that means defining an enumeration data type to list all the possible special cases and switch-casing between them. This again is error-prone, defines a lot of values only used with one function and still makes return value to signify a special case. This, in my opinion is not good.
How about exceptions? They were made to handle special cases that require some special actions? No. In my opinion exceptions should be used in situations where a whole operation can fail a number of ways. Exceptions should be thrown when the programmer feels they are necessary, not when a library programmer does so. This is because a llibrary programmer can not quantify an operation in the program, and as such cannot generate exceptions relevat to that program logic. The program above could be written with exceptions something like this:
Code:
class ZeroDivisorException: public exception;
float div(float n, float d) {
if(d==0) throw ZeroDivisorException();
return n/d;
}
int main() {
...
try {
z = div(x, y);
} catch(ZeroDivisionException e) {
(error handling)
}
...
return 0;
}
Good news: we now have return values dedicated to return values. Bad news: this is a needlessly heavy framework for something as simple as special cases in functions. Exceptions are a nice concept with some good uses, but it really does not fit here. These kind of special cases should be taken into account no matter what, and they are only relevat right where the function is called. Knowing somewhere down the line that somewhere someone divided by zero is not something anyone can handle in any smart way. The only place where thet can be addressed is right where the function is called. In my opinion, exceptions should always be related to the program's concepts. Consider the following example:
Code:
Book findBookByIBAN(string iban) {
...
Book b = database.query(ibanQuery);
return b;
}
Now if the database query function throws an exception QueryFailed, the caller may know that some query failed somewhere. This, again, is not something that can be handled in any smart way. This is why it is a good practice to define program-specific exceptions to translate generic errors to something related to the program's concepts.
Code:
class BookNotFoundException: public exception;
Book findBookByIBAN(string iban) {
...
try {
Book b = database.query(ibanQuery);
} catch(QueryFailed fail) {
throw BookNotFoundException();
}
return b;
}
See what happened? The database layer gets no actual benefit from using exceptions.
In my opinion, special cases should be handled differently. Both of the approaches above have their merits, but both attempt to make something that does not suit handling special cases into something that does. I propose something like this:
Code:
float div(float n, float d) {
if(d==0) special ZeroDivisor;
return n/d;
}
int main() {
...
div(x, y) {
ZeroDivisor: (error handling)
}
...
return 0;
}
or
Code:
class BookNotFoundException: public exception;
Book findBookByIBAN(string iban) {
...
Book b = database.query(ibanQuery) {
QueryFailed: throw BookNotFoundException();
}
return b;
}
The custom exception is still thrown, because not finding a book is not something the caller may need to address. It is not a special case, it is an exception.
This could be handled compile-time, because special cases must be handled right after the function call. In my opinion these special cases should be defined as such, that the programmer should address them immediately no matter what. Not making a handler for a defined special case would raise at least a compiler warning. No more gazillions of small exceptions, try-catches, one-function enum return value definitions, and such.
Let me say, after trying to explain this idea to some of my friends over IRC some people asked what this gives over exceptions. I hope I got myself over better here. I really do think there is something to this idea.