On Wednesday, 6 August 2025 at 16:19:17 UTC, Nick Treleaven wrote:
On Wednesday, 6 August 2025 at 15:43:01 UTC, Brother Bill wrote:
How is this done in D?
I thought the following would work, but the compiler doesn't
like `this.count` as a default argument:
```d
struct Counter {
int count;
void incrementBy(int increment, int preCount = this.count)
in {
assert(increment >= 0, "increment must be zero or
greater");
}
out {
assert(count == preCount + increment);
}
do {
this.count += increment;
}
}
```
And I exp
ect you'd like to avoid adding a function parameter
anyway.
This hack gets the job done, at the cost of an extra struct
member and an assignment.
If this code is conditionally compiled, then the extra struct
member and the extra setting of oldCount can be removed from
release (production) version.
The additional code is manually entered for now as a "proof of
concept".
```
import std.stdio;
void main() {
Counter counter = { count: 42 };
writeln("counter(42): ", counter.count);
counter.incrementBy(100);
writeln("after incrementBy(100): ", counter.count);
}
struct Counter {
int count;
private int oldCount;
void incrementBy(int increment)
in {
assert (increment >= 0, "increment must be non-negative");
}
out {
assert(count == oldCount + increment, "count = old count +
increment");
}
do {
// Capture oldCount
oldCount = count;
// body
count += increment;
}
}
```
Can we do better than this?
IMHO, DbC (Design by Contract) is one of the great features in D
"borrowed" from Eiffel.
It would be even better with old(count) or old count, where old
would be a "keyword" specially treated in the postcondition "out"
block only. It would capture the count member implicitly at the
start of the do block.
```
out {
assert(count == old count + increment, "count = old count +
increment");
}
```