digitalmars.D - iota steps, nothrow, naturals and more
- bearophile (78/78) Mar 16 2014 The uncooked musings of this post are not very important compared
- bearophile (6/10) Mar 16 2014 Please vote the issue, now you have 20 votes :-)
The uncooked musings of this post are not very important compared to other threads. Currently this doesn't compile because step could be 0: void main() nothrow { import std.range: iota; uint step = 2; iota(1, 10, step); } temp.d(4,9): Error: 'std.range.iota!(int, int, uint).iota' is not nothrow But I'd like to use iota/3 (where /3 is its arity) in nothrow functions too. There several ways to do this. One way is to prove n can't be zero, but currently D is not this smart, and perhaps it will never be. Another solution is to use types (this doesn't compile, I think because iota has problems with other types): struct Natural { uint x; alias x this; this(in long input) pure nothrow in { assert(input > 0 && input < uint.max); } body { this.x = cast(uint)input; } } void main() nothrow { import std.range: iota; enum step = 2.Natural; iota(1.Natural, 10.Natural, step); } Here I have defined a positive Natural type. Once iota/3 is aware of such Phobos-defined Natural type, iota/3 can be specialized to be nothrow if the step has such type. Here step is a manifest constant so the pre-condition of its contructor runs at compile-time. A better solution could be to add to D "enum pre-conditions" that I have discussed elsewhere: struct Natural { uint x; alias x this; this(in long input) pure nothrow enum in { assert(input > 0 && input < uint.max); } in { assert(input > 0 && input < uint.max); } body { this.x = cast(uint)input; } } Currently you need enum or something like this to force the evaluation of Natural ctor pre-condition at compile-time: enum CT(alias x) = x; void main() nothrow { import std.range: iota; auto step = CT!(Natural(2)); iota(1.Natural, 10.Natural, step); } A hypothetical solution is to carry around the interval of immutable values between lines and use the contracts to shape such intervals, as asked here: https://d.puremagic.com/issues/show_bug.cgi?id=10594 void foo(immutable uint step) nothrow in { assert(step > 0); } body { iota(1, 10, step.Natural); } But even implementing issue 10594 is not enough to do this, because the range value of step is lost at the call (instantiation) point of Natural. Some related ideas suggest that __traits could be used to read the range of a value in user code: uint x; static assert(__traits(value_range, x) == [uint.min, uint.max]); Perhaps there are ways to make this information useful inside an "enum precondition". Bye, bearophile
Mar 16 2014
A hypothetical solution is to carry around the interval of immutable values between lines and use the contracts to shape such intervals, as asked here: https://d.puremagic.com/issues/show_bug.cgi?id=10594Please vote the issue, now you have 20 votes :-) Pre-state (old), the shaping of in/immutable value ranges with contracts, and few more things make D contract programming more useful. Bye, bearophile
Mar 16 2014