Question about contracts on methods.

Peter C. Chapin pcc482719 at gmail.com
Sat Nov 28 12:14:41 PST 2009


Hi!

I'm rather new to D and I'm experimenting with its support for 
contracts. I'm using dmd v1.51 on Windows.

Whenever I learn a new language I usually start by implementing a few 
"classic" components to get a feeling for how the language's features 
work in a pseudo-realistic setting. A class representing calendar dates 
is one of my favorite exercises. Here is a method next() of such a class 
that advances a Date to the next date on the calendar.

class Date {

    // etc...    

    void next()
    {
        if (day_m != days_in_month()) ++day_m;
        else {
            day_m = 1;
            if (month_m != 12) ++month_m;
            else {
                month_m = 1;
                ++year_m;
            }
        }
    }
}

The method days_in_month() is a private method in the class that returns 
the number of days in the "current" month. The fields day_m, month_m, 
and year_m are also private with the obvious meaning.

Okay, so far so good. Now I want to add a post condition on this method 
asserting that the date it computes is actually later than the original 
date. In my post condition I will need to access both the new values of 
day_m, month_m and year_m *and* the original values of those fields. 
There doesn't seem to be an easy way to do that.

I appreciate that I might need to explictly make my own copies of the 
original field values, but it seems like I can't do that locally in next
() because there is no place to declare the copies where they would be 
in scope in the post condition. Do I have to add three additional fields 
to the class itself and then copy the original values in the body of 
next()? Like this:

class Date {

    private {
        int original_day_m;
        int original_month_m;
        int original_year_m;
    }

    void next()
    out {
        assert(
            day_m > original_day_m ||
           (day_m == 1 && month_m > original_month_m) ||
           (day_m == 1 && month_m == 1 && year_m > original_year_m));
    }
    body {
        original_day_m   = day_m;
        original_month_m = month_m;
        original_year_m  = year_m;

        if (day_m != days_in_month()) ++day_m;
        else {
            day_m = 1;
            if (month_m != 12) ++month_m;
            else {
                month_m = 1;
                ++year_m;
            }
        }
    }
}

Not only does this seem awkward it has the disadvantage that there is 
now code related to the post conditions that won't be compiled out in 
the release build. Am I missing something? Surely this situation comes 
up often.

Peter


More information about the Digitalmars-d-learn mailing list