digitalmars.D.learn - Compile time range checking/asserts
- Borden Rhodes (32/32) Sep 14 2010 Good morning, list,
- bearophile (17/18) Sep 15 2010 I think Walter said that Ranged Types are a "failed feature" of Pascal/A...
- bearophile (11/14) Sep 15 2010 And the compiler in most situations doesn't "run" the invariant at compi...
Good morning, list,
I know that D has support for ranges in for-each statements and in array
bounds checking, but I'm curious if it also has a facility for compile-time
range checking or assertions on individual variables.
For example, using the Java Tutorial's venerable Bicycle class, say I
had a property <code>int gear;</code> which indicated the bicycle's current
gear. Let's say all bicycles of this class have 6 gears. Typically, I would
write a changeGear method as:
<code>
void changeGear(int newGear) {
if ( 1 <= newGear && newGear <= 6)
gear = newGear;
else
throw SomeKindOfException();
}
</code>
which would include the if statement to make sure that newGear would be passed
a number in the correct range and a throw statement to deal with cheaters.
Does D allow - or would there be logic in creating - an ability to define the
acceptable ranges when the variable is initialised? So, say I wanted gear
only to accept values between 1 and 6 inclusive. Could I declare something to
the effect of:
<code>int gear {1...6} = 1;</code>
Which could read, "create a new int, called gear, which only accepts values
between 1 and 6, inclusive, and initialise it to 1." Then, if I, or some
coder who forgot how many gears my Bicycle has, tried to call:
</code>bicycle.changeGear( 12 );</code>
the compiler would catch that <code>gear = newGear;</code> is assigning a
value out of range and throw a compile-time error. Can D do this? Should it
do this?
With thanks,
Borden
Sep 14 2010
Borden Rhodes:
<code>int gear {1...6} = 1;</code>
I think Walter said that Ranged Types are a "failed feature" of Pascal/Ada
lineage, but I don't agree and I think they are useful to increase code safety,
a possible syntax from yours:
typedef int { 1 ... 6 } Gear;
Using a struct with "alias this" and a struct invariant that enforces the
range, plus properties, is possible, but such struct:
- Doesn't act transparently as a int subclass;
- Syntax-wise it's longer to define;
- The invariant is not enforced in all situations.
struct Gear {
int g_ = 1;
this(int g) { this.g_ = g; }
invariant() { assert(this.g_ >= 1 && this.g_ <= 6); }
property void g(int x) { this.g_ = x; }
property int g() { return this.g_; }
alias g this;
}
Bye,
bearophile
Sep 15 2010
- Doesn't act transparently as a int subclass; - Syntax-wise it's longer to define; - The invariant is not enforced in all situations.And the compiler in most situations doesn't "run" the invariant at compile time (unless you define an enum). Well, a test shows that it doesn't work (dmd 2.048) even if you use enum, I don't know why: struct Foo { int x; this(int y) { this.x = y; } } void main() { enum Foo f = Foo(1); } Bye, bearophile
Sep 15 2010








bearophile <bearophileHUGS lycos.com>