February 17, 2022 Re: [OT] The Usual Arithmetic Confusions | ||||
---|---|---|---|---|
| ||||
Posted in reply to Walter Bright | On Thursday, 17 February 2022 at 22:41:59 UTC, Walter Bright wrote:
> On 2/17/2022 12:11 PM, Paul Backus wrote:
>> Yeah, implicit signed-to-unsigned conversion is really nasty. Even if we keep the rest of the C-style promotion rules, getting rid of that one would still be a big improvement.
>
> There is a simple solution you can use: never use unsigned integers. I'm not being facetious. Many languages do not have unsigned integer types.
The fact that language built-ins like an array's .length property are unsigned make this somewhat difficult to do in D.
|
February 17, 2022 Re: [OT] The Usual Arithmetic Confusions | ||||
---|---|---|---|---|
| ||||
Posted in reply to Walter Bright | On Thursday, 17 February 2022 at 22:41:59 UTC, Walter Bright wrote:
> On 2/17/2022 12:11 PM, Paul Backus wrote:
>> Yeah, implicit signed-to-unsigned conversion is really nasty. Even if we keep the rest of the C-style promotion rules, getting rid of that one would still be a big improvement.
>
> There is a simple solution you can use: never use unsigned integers. I'm not being facetious. Many languages do not have unsigned integer types.
But that would mean you have to give up D's arrays. All I did was feed the length of an array to std.range.iota.
|
February 17, 2022 Re: [OT] The Usual Arithmetic Confusions | ||||
---|---|---|---|---|
| ||||
Posted in reply to bachmeier | On 2/17/2022 2:51 PM, bachmeier wrote:
> But that would mean you have to give up D's arrays. All I did was feed the length of an array to std.range.iota.
Cast it to ptrdiff_t and you'll be fine.
|
February 18, 2022 Re: [OT] The Usual Arithmetic Confusions | ||||
---|---|---|---|---|
| ||||
Posted in reply to Walter Bright | On Thursday, 17 February 2022 at 22:41:59 UTC, Walter Bright wrote:
> On 2/17/2022 12:11 PM, Paul Backus wrote:
>> Yeah, implicit signed-to-unsigned conversion is really nasty. Even if we keep the rest of the C-style promotion rules, getting rid of that one would still be a big improvement.
>
> There is a simple solution you can use: never use unsigned integers. I'm not being facetious. Many languages do not have unsigned integer types.
Then you don't get to know the length of a slice, this is going to be really limiting really quick.
|
February 18, 2022 Re: [OT] The Usual Arithmetic Confusions | ||||
---|---|---|---|---|
| ||||
Posted in reply to Walter Bright | On Thursday, 17 February 2022 at 23:23:40 UTC, Walter Bright wrote:
> On 2/17/2022 2:51 PM, bachmeier wrote:
>> But that would mean you have to give up D's arrays. All I did was feed the length of an array to std.range.iota.
>
> Cast it to ptrdiff_t and you'll be fine.
If only there were some way we could remind people to use an explicit cast in situations like these...
|
February 18, 2022 Re: [OT] The Usual Arithmetic Confusions | ||||
---|---|---|---|---|
| ||||
Posted in reply to bachmeier | On 17.02.22 18:53, bachmeier wrote:
> On Friday, 28 January 2022 at 02:15:51 UTC, Paul Backus wrote:
>> Unfortunately, this is also one of the areas of D that comes directly from C, so D programmers have to watch out for these as well.
>
> Here's a lovely one I wrote about yesterday in Learn:
>
> ```
> import std.conv, std.range, std.stdio;
>
> void main() {
> writeln(iota(5, 0, -1));
> writeln(iota(5, -1, -1));
> writeln(iota(5.to!uint, -1, -1));
> writeln(iota(5.to!uint, 0, -1));
> writeln(-1.to!uint);
> auto z = -1;
> writeln(z.to!uint);
> }
> ```
>
> Which delivers the following output:
>
> ```
> [5, 4, 3, 2, 1]
> [5, 4, 3, 2, 1, 0]
> []
> [5, 4, 3, 2, 1]
> 4294967295
> std.conv.ConvOverflowException@/usr/include/dmd/phobos/std/conv.d(567): Conversion negative overflow
> ----------------
> ??:? pure @safe bool std.exception.enforce!(bool).enforce(bool, lazy object.Throwable) [0x555fe1c5c946]
> ??:? pure @safe uint std.conv.toImpl!(uint, int).toImpl(int) [0x555fe1c6f1ff]
> ??:? pure @safe uint std.conv.to!(uint).to!(int).to(int) [0x555fe1c6f1d0]
> ??:? _Dmain [0x555fe1c5594c]
> ```
>
> All I wanted was a function that iterates through the elements of an array starting at the end. The only time you have a problem is if you want to include the first element of the array.
>
> A simple solution is to add a `-scottmeyers` switch that retains full compatibility with C, but sets the default as a language that is productive.
Not defending C rules at all or how Phobos is handling them, but if you want a range with all array indices in reverse, there is a very simple way to state just that:
```d
import std.conv, std.range, std.stdio;
void main() {
auto v = [1, 2, 3, 4, 5];
writeln(iota(v.length).retro);
}
```
In general, I avoid using negation/subtraction if anything unsigned is involved. There is usually another way to write it, in this case it is even much simpler, more descriptive, and it will work correctly for long arrays. (`int`/`uint` are not large enough to address modern amounts of RAM. However, I guess instead of avoiding negation/subtraction, it can also make sense to do index computations with `long` instead of `size_t`.)
|
February 17, 2022 Re: [OT] The Usual Arithmetic Confusions | ||||
---|---|---|---|---|
| ||||
Posted in reply to deadalnix | On 2/17/2022 4:07 PM, deadalnix wrote:
> Then you don't get to know the length of a slice, this is going to be really limiting really quick.
cast(ptrdiff_t)length
|
February 17, 2022 Re: [OT] The Usual Arithmetic Confusions | ||||
---|---|---|---|---|
| ||||
Posted in reply to Walter Bright | On 2/17/2022 8:31 PM, Walter Bright wrote:
> On 2/17/2022 4:07 PM, deadalnix wrote:
>> Then you don't get to know the length of a slice, this is going to be really limiting really quick.
>
> cast(ptrdiff_t)length
ptrdiff_t len = array.length;
also works.
|
February 18, 2022 Re: [OT] The Usual Arithmetic Confusions | ||||
---|---|---|---|---|
| ||||
Posted in reply to Paul Backus | On Thursday, 17 February 2022 at 21:35:00 UTC, Paul Backus wrote:
>
> Memory safety is about avoiding undefined behavior, not avoiding bugs in general. Implicitly casting an int to a uint can certainly cause bugs in a program, but it cannot introduce undefined behavior unless you are already doing something unsafe with the result (like indexing into an array without bounds checking).
Well, strong type safety is a component of memory safety.
Now a 'bug' is where the programmer takes the average of two unsigned integers, and it results in an overflow. Here, correctness is the programmers responsibility.
On the otherhand, implicit conversion of uint to int is inherently unsafe, since the compiler cannot determine whether the coercion 'avoids undefined behaviour'.
On that basis, it should just not do it - and instead, make the programmer take responsibilty.
Thus once again, the programmer is in charge - which is, as it should be.
|
February 18, 2022 Re: [OT] The Usual Arithmetic Confusions | ||||
---|---|---|---|---|
| ||||
Posted in reply to Walter Bright | On 18.02.22 05:32, Walter Bright wrote:
> On 2/17/2022 8:31 PM, Walter Bright wrote:
>> On 2/17/2022 4:07 PM, deadalnix wrote:
>>> Then you don't get to know the length of a slice, this is going to be really limiting really quick.
>>
>> cast(ptrdiff_t)length
>
> ptrdiff_t len = array.length;
>
> also works.
Except perhaps for somewhat long arrays in a 32-bit program.
|
Copyright © 1999-2021 by the D Language Foundation