comp.lang.ada
 help / color / mirror / Atom feed
From: Robert A Duff <bobduff@shell01.TheWorld.com>
Subject: Re: What would be the Ada solution?
Date: Fri, 04 Feb 2011 12:38:34 -0500
Date: 2011-02-04T12:38:34-05:00	[thread overview]
Message-ID: <wcc4o8jya1x.fsf@shell01.TheWorld.com> (raw)
In-Reply-To: 0aa67233-4210-483b-b35c-8e872f87cb8f@r21g2000yqd.googlegroups.com

KK6GM <mjsilva@scriptoriumdesigns.com> writes:

> A colleague is working on some old code, written in C, that uses an
> "out of range" integer value to indicate no valid value.  Thus, a
> default value (in this case 0x7FFFFFFF) means no value has been
> entered.  All code that uses any values should check for this no-value
> and act accordingly, but of course not all the code actually does
> that, and there are odd cases where the no-value value gets processed
> as a valid value and then Bad Things Happen.

And another problem is that you probably have lots of
unnecessary/redundant checks for the no-value case.  That's "defensive
programming", which Bertrand Meyer wisely said is a bad idea.  But it's
sort of necessary in C, because it's hard to keep track of which code
actually needs the checks -- better to clutter the code with redundant
junk than to miss some.

There are lots of ways to represent the "no valid value" value in Ada.
You suggested a magic number.  Mark Lorenzen suggested a variant record.

Let's go with the magic number:

   No_Value : constant := 2**31 - 1;
   pragma Assert (No_Value = 16#7FFF_FFFF#);

You don't want to check for No_Value all over the place.
You want to check for it on input, and let the rest of your
program operate on valid values, and be sure that No_Value
doesn't sneak into the rest of the program.

You could do something like this:

   type Optional_T is range -2**31 .. No_Value with
     Default_Value => No_Value;

That means every object of subtype Optional_T will be initialized
to No_Value, unless you explicitly initialize it to something else.

   type T is new Optional_T with
     Static_Predicate => T /= No_Value;

That means every object of subtype T will be checked that's
it's not No_Value, on assignment, parameter passing, etc.
And T inherits the Default_Value.

You input values of type Optional_T.  You then check whether they
are valid, and convert them to type T.  The rest of your program
is written in terms of type T.  If you try to pass an Optional_T
to a parameter of type T, you get a compile time error.
You can convert:

    procedure P(X : T);
    
    Possibly_Invalid : Optional_T := Read_From_Input(...);

    P (T (Possibly_Invalid)); -- Might raise an exception

but the conversion will raise an exception if the value is No_Value.

If you declare an uninitialized variable of type T,
you will get an exception, because the default value
violates the predicate.  If you're lucky, your compiler
will warn about that at compile time.

Your objects (including parameters, record components, etc)
are of type T or Optional_T, so it's easy to tell which ones
are safe.  Hopefully, there are few Optional_T objects,
and few places where you convert, so you can be careful
about those.

Depending on what you're trying to do, you might want to make
one or both types private.

If the run-time checks are too slow (which is unlikely!),
you can always suppress them, and get efficiency equal to
the C code.

Default_Value and Static_Predicate are Ada 2012 features.
Both are implemented in the latest version of GNAT,
but I don't know about the public version(s).
You can do more or less the same thing in Ada 2005, except that to
get a default value, you have to wrap the thing in
a record, and you can use range constraints instead of predicates.

You could probably do more-or-less the same thing in C,
but I think it would take a fair amout of horsing around.

Predicates are my favorite feature of Ada 2012!
And user-defined integer types are one of my favorite
features of Ada 83.

- Bob



      parent reply	other threads:[~2011-02-04 17:38 UTC|newest]

Thread overview: 9+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2011-02-04 16:33 What would be the Ada solution? KK6GM
2011-02-04 16:38 ` Mark Lorenzen
2011-02-04 16:57 ` Robert A Duff
2011-02-04 18:59   ` Georg Bauhaus
2011-02-04 19:33     ` Robert A Duff
2011-02-04 17:14 ` mockturtle
2011-02-04 17:47   ` Robert A Duff
2011-02-04 17:26 ` Dmitry A. Kazakov
2011-02-04 17:38 ` Robert A Duff [this message]
replies disabled

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox