assert(obj) is a mystery

Davidson Corry davidsoncorry at comcast.net
Tue Nov 8 21:51:46 PST 2011


Over on the digitalmars.D newsgroup,
On 11/8/2011 2:35 PM, Alex Rønne Petersen wrote (in a thread
entitled "assert(obj) is an atrocity"):
 > Hi,
 >
 > As the title suggests, I'm going to be rather blunt about this.
 > assert(obj) testing the invariant *without* doing a null check is insane
 > for the following reasons:
 >
 > 1) It is not what a user expects. It is *unintuitive*.
 > 2) assert(!obj) does an is-null check. assert(obj) is a completely
 > broken opposite of this.
 > 3) No AssertError is thrown, which is the entire point of the built-in
 > assert().
 > 4) The few added instructions for the null check hardly matter in a
 > *debug* build of all things.
 >
 > I don't mind assert(obj) testing the invariant of obj. In fact, that
 > very much makes sense. But please, please, *please* check the object for
 > null first. This is a random inconsistency in the language with no other
 > justification than "seg faults are convenient in a debugger". By the
 > same logic, we might as well not have array bounds checks. However, the
 > state of things is that array bounds checks are emitted by default and
 > users can disable them for e.g. a release build. I don't see why this
 > case is any different.
 >
 > - Alex

OK. Not addressing Alex's objections at all, it's not clear to me why 
anyone would *need* to test the invariant of an object. Aside from the 
fact that, anytime you actually use the object, its invariant will get 
tested (twice)...

Unless I misunderstand something about design-by-contract (always a 
possibility), the invariant of an object holds anytime you have access 
to an object outside of its public interface. The only times an 
invariant does *not* hold are
(a) while the object is being constructed -- in fact, the *whole 
purpose* of the constructor is to establish the invariant! +++
(b) while an object is executing "private code", i.e. internally during 
a method
(c) after the object has been destroyed

In that light, it seems to me that if you can get a non-null reference 
to obj at all, its invariant must hold. Stating that another way, if you 
*can* get a non-null reference to an object whose invariant does not 
hold, the_language_itself_is_broken! No?

What am I missing here? What is the purpose of  assert(obj)  having 
semantics beyond  assert (obj !is null) ??

-- Davidson

+++ The notion that the ONLY purpose of the constructor is to establish 
the invariant is a strict formalism. In practice, many constructors 
perform additional initialization beyond invariant-establishment, as a 
convenience. Such additional initialization could be factored out into 
separate methods.

Also, D's insistence that an object be fully-fledged once each of its 
member fields receives its .init value -- which could happen if the 
later stages of a constructor throws, or if a live object's .clear() 
method is called -- constrains what the invariant can guarantee. For 
that reason, you need to take care that the constructor does *not* 
throw, and that .clear() is not called, if you have an object that 
really isn't "live" without some fancy work having been completed on it.








More information about the Digitalmars-d-learn mailing list