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