Thread overview | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|
|
February 19, 2018 Could that bug be catch using D's way? | ||||
---|---|---|---|---|
| ||||
I'm pretty sure something could be done with Ada's type range but what we could do using D? |
February 19, 2018 Re: Could that bug be catch using D's way? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Marc | 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
|
February 19, 2018 Re: Could that bug be catch using D's way? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Simen Kjærås | 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 |
February 19, 2018 Re: Could that bug be catch using D's way? | ||||
---|---|---|---|---|
| ||||
Posted in reply to rikki cattermole | 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
|
February 19, 2018 Re: Could that bug be catch using D's way? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Simen Kjærås | 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
}
|
February 19, 2018 Re: Could that bug be catch using D's way? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Basile B. | 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 |
February 19, 2018 Re: Could that bug be catch using D's way? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Simen Kjærås | 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.
|
February 19, 2018 Re: Could that bug be catch using D's way? | ||||
---|---|---|---|---|
| ||||
Posted in reply to rikki cattermole | 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 |
Copyright © 1999-2021 by the D Language Foundation