assume, assert, enforce, @safe
Timon Gehr via Digitalmars-d
digitalmars-d at puremagic.com
Thu Jul 31 14:39:48 PDT 2014
On 07/31/2014 11:01 PM, ponce wrote:
> Could you expand on what you consider input? For example, if a
> function has an "in" contract that validates input parameters, is
> the determination that a parameter is invalid a program bug or
> simply invalid input? ...
>
The assertions in an 'in' contracts are obligations at the call site.
I.e., the code:
void baz(int x){
assert(x>2);
// ...
}
is buggy.
The code
void foo(int x)in{ assert(x>2); }body{ assert(x>2); }
is correct.
The code:
void bar(int x){ foo(x); }
is buggy.
The code
void bar(int x){
enforce(x>2);
foo(x);
}
is fine.
> This also puzzles me. There is the point where the two types of errors
> blend to the point of being uncomfortable.
>
> Eg: a program generates files in X format and can also read them with a
> X parser. Its X parser will only ever read output generated by itself.
> Should input errors in X parser be checked with assert or exceptions?
Use 'assert' for checking things which you expect to be true. But don't
be fooled, besides having some loosely checked code documentation, the
main reason to write down assertions is that they will occasionally fail
and tell you something interesting which you didn't know yet about your
program (as it was nicely formulated somewhere else in this thread.)
This makes assertions seem a little schizophrenic at times, but after
all, checking those assertions, which you _expect_, by definition, to be
no-ops anyway, may be too expensive for you and then they can be
disabled. I'd check what are the actual performance gains before doing
this though. You can also control assertions in a more fine-grained way
by guarding them with version statements.
Furthermore, use 'assert' as well in _in_ contracts, and think about
them being checked in the context of the caller as an obligation instead
of as being checked in your own function.
Use 'enforce' for things which you expect might be false sometimes and
that you may want to handle as an exception in this case.
I wouldn't think about 'enforce' as 'not checking program bugs' too hard
though. Maybe the bug is in code which does not actually expect the
exceptional path to be taken.
The difference between
void foo1(int x)in{ assert(x>2); }body{ ... }
and
void foo2(int x){
enforce(x>2);
}
Is that 'foo2' reliably throws an exception if the contents of x are not
greater than 2; this is part of it's behaviour and would be part of its
documentation, while 'foo1' just states in its documentation that it
will do a certain thing _provided_ x is greater than 2, and that its
behaviour is left unspecified otherwise.
Or that's what I would say anyway if there wasn't talk about turning
assertions into assumptions in -release. If nothing changes, always use
version(assert) to guard your assert statements unless you want their
failures to be undefined behaviour in -release mode.
More information about the Digitalmars-d
mailing list