On Wed, 30 May 2012 11:47:34 -0400, Jens Mueller <[email protected]> wrote:

Steven Schveighoffer wrote:

case 2:

int main(string[] args)
{
   writeln(invert(to!double(args[1])); // clearly a catchable error
}

This should be
int main(string[] args)
{
   auto arg = to!double(args[1]);
   enforce(arg != 0);
   writeln(invert(arg));
}

The enforce is needed because args[1] is user input. If the programmer
controlled the value of arg and believes arg != 0 always holds then no
enforce would be needed.

Doesn't this make sense?

Yes and no. Yes, the ultimate result of what you wrote is the desired functionality. But no, I don't think you have properly solved the problem.

Consider that user data, or environment data, can come from anywhere, and at any time. Consider also that you have decoupled the function parameter validation from the function itself! Ideally, invert should be the one deciding whether the original data is valid or not. In order to write correct code, I must "know" what the contents of invert are as the writer of main. I'd rather do something like:

int main(string[] args)
{
   auto argToInvert = to!double(args[1]);
   validateInvertArgs(argToInvert); // uses enforce
   invert(argToInvert);
}

Note that even *this* isn't ideal, because now the author of invert has to write and maintain a separate function for validating its arguments, even though invert is *already* validating its arguments.

It's almost as if, I want to re-use the same code inside invert that validates its arguments, but use a different mechanism to flag an error, depending on the source of the arguments.

It can get even more tricky, if say a function has two parameters, and one is hard-coded and the other comes from user input.

PS
For the record, I think (like most) that Errors should like Exceptions
work with scope, etc. The only arguments against is the theoretical
possibility of causing more damage while cleaning up. I say theoretical
because there was no practical example given. It seems that it may cause
more damage but it does not need to. Of course, if damage happens it's
the programmers fault but it's also the programmer's fault if he does
not try to do a graceful shutdown, i.e. closing sockets, sending a crash
report, or similar.

Indeed, it's all up to the programmer to handle the situation properly. If an assert occurs, the program may be already in an invalid state, and *trying to save* files or close/flush databases may corrupt the data.

My point is, it's impossible for the runtime to know that your code is properly handling the error or not, and that running all the finally/scope blocks will not be worse than not doing it.

-Steve

Reply via email to