On Friday, November 03, 2017 12:34:22 Mark via Digitalmars-d wrote: > On Friday, 3 November 2017 at 02:32:41 UTC, Jonathan M Davis > > wrote: > > Pretty much the only case where out contracts work well is when > > you have a very specific, testable condition that all results > > must have and which does not depend on the input, and most > > functions simply don't work that way. > > - Jonathan M Davis > > Can you give an example of a function for which this doesn't work?
Um, most functions? Heck, take a really simply one like sqrt. All you have to check in the out contract is the return value. You have no idea what was passed in. So, how would you write an out contract verifying that you got the correct number? If you also had access to the input, then you could do the reverse operation by squaring the result to see if it matched the input (assuming of course that floating point rounding errors don't make that not work), but you don't have access to the input. And even if you did have access to the input, some functions consume their input without any way to save it (e.g. an input range that isn't a forward range), and not all operations are reversible - e.g. if you have a hash function, you can't get the original value back from it to check against what was passed in. So, for a lot of stuff, even if you had the original input, you would have to essentially implement the function a second time in the out contract to verify the result, and who's to say that the implementation in the out contract isn't just as buggy as the one in the main function (assuming that it's even different at all)? And that's still assuming that you had access to the input parameters in the out contract, which you don't. In order to have an out contract be of any use, it needs to be able to verify something about the state of the result without having any clue what the input was. You essentially need to be able to pass the result to a function that says whether an arbitrary result is valid or not. Something like sort can do that, because you know that the result is supposed to be sorted, and that's a testable condition (albeit a condition that's not very cheap to test), but for most functions there simply doesn't exist a test for knowing whether the result is correct by only looking at the result. On the other hand, if you know what output a function is supposed to have for a given input, it's trivial to test that with a unit test. The only thing that's worse about that is that if you could somehow test the result in an out contract, then it's possible to test the result for every invocation of that function instead of just testing a specific set of inputs. So, upon occasion, an out contract may be useful, but it rarely is, and even if it is, if your unit tests are good, they'll likely catch all of the problems that the out contract would catch, and the out contract would slow down every non-release build, so if the unit tests are enough to catch the bugs, then having the out contract just needlessly slows down your program (which may or may not matter, depending on what you do with non-release builds, but it can matter). So, all in all, I think that unit tests solve the problem that out contracts are trying to solve and do it in a way that works in general, whereas out contracts only work in specific cases. So, I don't see much point in using them. - Jonathan M Davis
