www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Could that bug be catch using D's way?

reply Marc <jckj33 gmail.com> writes:
I'm pretty sure something could be done with Ada's type range but 
what we could do using D?
Feb 19 2018
parent reply Simen =?UTF-8?B?S2rDpnLDpXM=?= <simen.kjaras gmail.com> writes:
On Monday, 19 February 2018 at 12:58:45 UTC, Marc wrote:
 I'm pretty sure something could be done with Ada's type range 
 but what we could do using D?
We can easily define a range type in D. The simple example below probably has awful performance and many holes, but outlines the basic idea. It will not have compile-time bounds checks, but can be used as an int when it needs to, and enforces at run-time that the value is within the specified bounds. import std.format : format; import std.exception : enforce; struct Range(T, T min, T max, T defaultValue = 0) if (defaultValue >= min && defaultValue <= max) { private T payload; this(T value) { this = value; } T get() { return payload; } alias get this; Range opBinary(string op)(T value) { return Range(mixin("payload "~op~" value")); } ref Range opOpAssing(string op)(T value) { this = Range(mixin("payload "~op~" value")); return this; } ref Range opAssign(T value, string file = __FILE__, int line = __LINE__) { enforce(value <= max && value >= min, format("Value needs to be between %s and %s, not %s.", min, max, value), file, line); payload = value; return this; } } unittest { Range!(int, 3, 15, 3) a = 4; a = 16; // foo.d(38): Value needs to be between 3 and 15, not 16. int n = a; } It currently does no sensible testing of what operators it allows, and does not support unary operators. Other potential improvements include merging of bounds when the other operand is a range as well (so Range!(int, 3, 6) + Range!(int, 2, 8) returns a Range!(int, 5, 14)). Perhaps a more sensible default value would be min(maxValue, max(0, minValue)). -- Simen
Feb 19 2018
parent reply rikki cattermole <rikki cattermole.co.nz> writes:
On 19/02/2018 1:24 PM, Simen Kjærås wrote:
 On Monday, 19 February 2018 at 12:58:45 UTC, Marc wrote:
 I'm pretty sure something could be done with Ada's type range but what 
 we could do using D?
We can easily define a range type in D. The simple example below probably has awful performance and many holes, but outlines the basic idea. It will not have compile-time bounds checks, but can be used as an int when it needs to, and enforces at run-time that the value is within the specified bounds. import std.format : format; import std.exception : enforce; struct Range(T, T min, T max, T defaultValue = 0) if (defaultValue >= min && defaultValue <= max) {     private T payload;     this(T value)     {         this = value;     }     T get() { return payload; }     alias get this;     Range opBinary(string op)(T value)     {         return Range(mixin("payload "~op~" value"));     }     ref Range opOpAssing(string op)(T value)     {         this = Range(mixin("payload "~op~" value"));         return this;     }     ref Range opAssign(T value, string file = __FILE__, int line = __LINE__)     {         enforce(value <= max && value >= min, format("Value needs to be between %s and %s, not %s.", min, max, value), file, line);         payload = value;         return this;     } } unittest {     Range!(int, 3, 15, 3) a = 4;     a = 16; // foo.d(38): Value needs to be between 3 and 15, not 16.     int n = a; } It currently does no sensible testing of what operators it allows, and does not support unary operators. Other potential improvements include merging of bounds when the other operand is a range as well (so Range!(int, 3, 6) + Range!(int, 2, 8) returns a Range!(int, 5, 14)). Perhaps a more sensible default value would be min(maxValue, max(0, minValue)). --   Simen
https://dlang.org/phobos/std_experimental_checkedint.html#.Checked.min
Feb 19 2018
next sibling parent reply Simen =?UTF-8?B?S2rDpnLDpXM=?= <simen.kjaras gmail.com> writes:
On Monday, 19 February 2018 at 13:33:34 UTC, rikki cattermole 
wrote:
 https://dlang.org/phobos/std_experimental_checkedint.html#.Checked.min
Can't seem to get that to work, so I assumed it's not meant to be used that way: import std.experimental.checkedint; struct MyHook { enum min(T) = 3; enum max(T) = 15; static B onLowerBound(T, B)(T value, B bound) { assert(0); } static B onUpperBound(T, B)(T value, B bound) { assert(0); } } unittest { Checked!(int, MyHook) a; a = 22; assert(a != 22); // This assert triggers, not the others. } -- Simen
Feb 19 2018
parent reply Basile B. <b2.temp gmx.com> writes:
On Monday, 19 February 2018 at 13:51:50 UTC, Simen Kjærås wrote:
 On Monday, 19 February 2018 at 13:33:34 UTC, rikki cattermole 
 wrote:
 https://dlang.org/phobos/std_experimental_checkedint.html#.Checked.min
Can't seem to get that to work, so I assumed it's not meant to be used that way: import std.experimental.checkedint; struct MyHook { enum min(T) = 3; enum max(T) = 15; static B onLowerBound(T, B)(T value, B bound) { assert(0); } static B onUpperBound(T, B)(T value, B bound) { assert(0); } } unittest { Checked!(int, MyHook) a; a = 22; assert(a != 22); // This assert triggers, not the others. } -- Simen
I had never used Checked and i discover that strangely there's no hook for opAssign. onLowerBound and onUpperBound works for +=, -=, *=, /=, %=, ^^=, &=, |=, ^=, <<=, >>=, and >>>=. But since init is 0, += works: struct MyHook { enum min(T) = 3; enum max(T) = 15; static B onLowerBound(T, B)(T value, B bound) { assert(0); } static B onUpperBound(T, B)(T value, B bound) { assert(0); } } unittest { Checked!(int, MyHook) a; a += 16; // triggers the onUpperBound assert }
Feb 19 2018
parent reply Simen =?UTF-8?B?S2rDpnLDpXM=?= <simen.kjaras gmail.com> writes:
On Monday, 19 February 2018 at 14:20:16 UTC, Basile B. wrote:
 I had never used Checked and i discover that strangely there's 
 no hook for opAssign. onLowerBound and onUpperBound works for 
 +=, -=, *=, /=, %=, ^^=, &=, |=, ^=, <<=, >>=, and >>>=. But 
 since init is 0, += works:
Ah, thanks. Filed a bug: https://issues.dlang.org/show_bug.cgi?id=18471 -- Simen
Feb 19 2018
parent Basile B. <b2.temp gmx.com> writes:
On Monday, 19 February 2018 at 21:34:04 UTC, Simen Kjærås wrote:
 On Monday, 19 February 2018 at 14:20:16 UTC, Basile B. wrote:
 I had never used Checked and i discover that strangely there's 
 no hook for opAssign. onLowerBound and onUpperBound works for 
 +=, -=, *=, /=, %=, ^^=, &=, |=, ^=, <<=, >>=, and >>>=. But 
 since init is 0, += works:
Ah, thanks. Filed a bug: https://issues.dlang.org/show_bug.cgi?id=18471 -- Simen
I think this is a design choice, it's too obvious to be an omission (it's even documented that opAssign is like the ctor). I'm curious to know what's the rationale though.
Feb 19 2018
prev sibling parent =?UTF-8?Q?Ali_=c3=87ehreli?= <acehreli yahoo.com> writes:
On 02/19/2018 05:33 AM, rikki cattermole wrote:

 https://dlang.org/phobos/std_experimental_checkedint.html#.Checked.min
Accompanying presentations: DConf 2017: https://www.youtube.com/watch?v=29h6jGtZD-U Google Tel Aviv: https://www.youtube.com/watch?v=es6U7WAlKpQ Andrei likes the second one more. Ali
Feb 19 2018