More on Ada2012 and its contracts
bearophile
bearophileHUGS at lycos.com
Wed Apr 10 04:07:55 PDT 2013
About the contract-based programming of Ada 2012 and related
matters, by Robert Dewar, president of AdaCore:
http://www.drdobbs.com/article/print?articleId=240150569&siteSectionName=architecture-and-design
There are trumpets about contract programming:
> But Ada 2012 does bring an "earth-shaking" advance
> the--introduction of
> contract-based programming, or what Eiffel programmers call
> "design by
> contract."
Compared to the usually long syntax of Ada, they are short and
nice enough:
> Suppose that Dedupe needs to meet the following requirements:
>
> On entry, the parameter Arr contains at least one
> duplicated element.
> On exit, all duplicates (and only the duplicates) have been
> removed, nothing new
> has been added, and the parameter Last shows the new upper
> bound.
>
>
> procedure Dedupe (Arr: in out Int_Array; Last : out
> Natural) with
> Pre => Has_Duplicates(Arr),
> Post => not Has_Duplicates( Arr(Arr'First .. Last) )
> and then (for all Item of Arr'Old =>
> (for some J in Arr'First .. Last =>
> Item = Arr(J)))
> -- Only duplicates removed
> and then (for all J in Arr'First .. Last =>
> (for some Item of Arr'Old =>
> Item = Arr(J)));
> -- Nothing new added
>
> where the helper function Has_Duplicates can be defined as
> follows:
>
> function Has_Duplicates(Arr : Int_Array) return Boolean is
> begin
> return (for some I in Arr'First .. Arr'Last-1 =>
> (for some J in I+1 .. Arr'Last =>
> Arr(I)=Arr(J)));
> end Has_Duplicates;
The ranges on scalar types are very useful:
> Besides preconditions and postconditions for subprograms, Ada
> 2012
> supports several other kinds of contracts. One category
> involves predicates
> on types: conditions that must always be met by values of the
> type. One of
> the most important such predicates, ranges on scalar types, has
> been part
> of the language since Ada 83:
>
> Test_Score : Integer range 0 through 100;
> Distance : Float range -100.0 .. 100.0;
This time I have understood a bit better the difference between
Static_Predicate and Dynamic_Predicate:
> Ada 2012's subtype predicates come in two forms,
> Static_Predicate and
> Dynamic_Predicate, employed depending on the nature of the
> expression
> that defines the predicate. For example:
>
> type Month is
> (Jan, Feb, Mar, Apr, May, Jun, Jul, Aug, Sep, Oct, Nov,
> Dec);
>
> subtype Long_Month is Month with
> Static_Predicate => Long_Month in (Jan, Mar, May, Jul, Aug,
> Oct, Dec);
>
> subtype Short_Month is Month with
> Static_Predicate => Short_Month in (Apr, Jun, Sep, Nov);
>
> subtype Even is Integer with
> Dynamic_Predicate => Even rem 2 = 0;
>
> The predicate is checked on assignment, analogous to range
> constraints:
>
> L : Long_Month := Apr; -- Raises Constraint_Error
> E : Even := Some_Func(X, Y); -- Check that result is even
>
> The static forms allow more compile-time checking. For example,
> in this
> case statement:
>
> case Month_Val is
> when Long_Month => …
> when Short_Month => …
> end case;
>
> the compiler will detect that Feb is absent. Dynamic predicates
> cannot
> be checked at compile time, but violations can still be
> detected at
> runtime. In general, predicates require runtime checks; when
> you assign
> a Month value to a Short_Month variable, a runtime check
> verifies that
> it has an appropriate value.
Bye,
bearophile
More information about the Digitalmars-d
mailing list