November 19, 2014 Re: 'int' is enough for 'length' to migrate code from x86 to x64 | ||||
---|---|---|---|---|
| ||||
Posted in reply to Don | On 11/19/14, 7:03 AM, Don wrote: > On Tuesday, 18 November 2014 at 18:23:52 UTC, Marco Leise wrote: > > Weird consequence: using subtraction with an unsigned type is nearly > always a bug. > > I wish D hadn't called unsigned integers 'uint'. They should have been > called '__uint' or something. They should look ugly. You need a very, > very good reason to use an unsigned type. > > We have a builtin type that is deadly but seductive. > I agree. An array's length makes sense as an unsigned ("an array can't have a negative length, right?") but it leads to the bugs you say. For example: ~~~ import std.stdio; void main() { auto a = [1, 2, 3]; auto b = [1, 2, 3, 4]; if (a.length - b.length > 0) { writeln("Can you spot the bug that easily?"); } } ~~~ Yes, it makes sense, but at the same time it leads to super unintuitive math operations being involved. Rust made the same mistake and now a couple of times I've seen bugs like these being reported. Never seen them in Java or .Net though. I wonder why... |
November 19, 2014 Re: 'int' is enough for 'length' to migrate code from x86 to x64 | ||||
---|---|---|---|---|
| ||||
Posted in reply to Andrei Alexandrescu | On 11/19/14, 1:46 PM, Andrei Alexandrescu wrote:
> On 11/19/14 2:03 AM, Don wrote:
>> We have a builtin type that is deadly but seductive.
>
> I agree this applies to C and C++. Not quite to D. -- Andrei
See my response to Don. Don't you think that's counter-intuitive?
|
November 19, 2014 Re: 'int' is enough for 'length' to migrate code from x86 to x64 | ||||
---|---|---|---|---|
| ||||
Posted in reply to ketmar | On 11/19/14, 10:21 AM, ketmar via Digitalmars-d wrote:
> On Wed, 19 Nov 2014 10:03:34 +0000
> Don via Digitalmars-d <digitalmars-d@puremagic.com> wrote:
>
>> No! No! No! This is completely wrong. Unsigned does not mean
>> "positive". It means "no sign", and therefore "wrapping
>> semantics".
>> eg length - 4 > 0, if length is 2.
>>
>> Weird consequence: using subtraction with an unsigned type is
>> nearly always a bug.
> negative length is a bug too.
How is that a bug? Can you provide some code that exhibits this?
|
November 19, 2014 Re: 'int' is enough for 'length' to migrate code from x86 to x64 | ||||
---|---|---|---|---|
| ||||
Posted in reply to David Gileadi | On Wednesday, 19 November 2014 at 16:02:50 UTC, David Gileadi wrote:
> On 11/19/14, 6:57 AM, ketmar via Digitalmars-d wrote:
>> On Wed, 19 Nov 2014 13:47:50 +0000
>> Don via Digitalmars-d <digitalmars-d@puremagic.com> wrote:
>>> If I have two pencils of length 10 cm and 15 cm, then the first
>>> one is -5 cm longer than the other.
>> and again "length" is not a relation. show me pencil of length -10 cm.
>> when you substractin lengthes, you got completely different type as a
>> result, not "length" anymore. ah, that untyped real-life math! ;-)
>
> To me the salient point is that this is not just a mess with real-life math but also with math in D: lengths are unsigned but people subtract them all the time. If they're (un)lucky this will return correct values for a while, but then someday the lengths may be reversed and the values will be hugely wrong:
>
> int[] a = [1, 2, 3];
> int[] b = [5, 4, 3, 2, 1];
>
> writefln("%s", b.length - a.length); // Yup, 2
> writefln("%s", a.length - b.length); // WAT? 18446744073709551614
>
> This is why I agree with Don that:
>
> > Having arr.length return an unsigned type, is a dreadful
> language
> > mistake.
I'd say length being unsigned is fine. The real mistake is that the difference between two unsigned values isn't signed, which would be the most "correct" behaviour. Let people cast the result if they want wrapping (or better, use a helper function to document the intentiion).
|
November 19, 2014 Re: 'int' is enough for 'length' to migrate code from x86 to x64 | ||||
---|---|---|---|---|
| ||||
Posted in reply to Ary Borenszweig | On 11/19/14 10:13 AM, Ary Borenszweig wrote:
> On 11/19/14, 1:46 PM, Andrei Alexandrescu wrote:
>> On 11/19/14 2:03 AM, Don wrote:
>>> We have a builtin type that is deadly but seductive.
>>
>> I agree this applies to C and C++. Not quite to D. -- Andrei
>
> See my response to Don. Don't you think that's counter-intuitive?
No. -- Andrei
|
November 19, 2014 Re: 'int' is enough for 'length' to migrate code from x86 to x64 | ||||
---|---|---|---|---|
| ||||
Posted in reply to Ary Borenszweig | On 11/19/14 10:09 AM, Ary Borenszweig wrote:
> On 11/19/14, 7:03 AM, Don wrote:
>> On Tuesday, 18 November 2014 at 18:23:52 UTC, Marco Leise wrote:
> >
>> Weird consequence: using subtraction with an unsigned type is nearly
>> always a bug.
>>
>> I wish D hadn't called unsigned integers 'uint'. They should have been
>> called '__uint' or something. They should look ugly. You need a very,
>> very good reason to use an unsigned type.
>>
>> We have a builtin type that is deadly but seductive.
>>
>
> I agree. An array's length makes sense as an unsigned ("an array can't
> have a negative length, right?") but it leads to the bugs you say. For
> example:
>
> ~~~
> import std.stdio;
>
> void main() {
> auto a = [1, 2, 3];
> auto b = [1, 2, 3, 4];
> if (a.length - b.length > 0) {
> writeln("Can you spot the bug that easily?");
> }
> }
> ~~~
>
> Yes, it makes sense, but at the same time it leads to super unintuitive
> math operations being involved.
>
> Rust made the same mistake and now a couple of times I've seen bugs like
> these being reported. Never seen them in Java or .Net though. I wonder
> why...
There are related bugs in Java too, e.g. I remember one in binary search where (i + j) / 2 was wrong because of an overflow. Also, Java does have a package for unsigned integers so apparently it's necessary.
Andrei
|
November 19, 2014 Re: 'int' is enough for 'length' to migrate code from x86 to x64 | ||||
---|---|---|---|---|
| ||||
Posted in reply to Andrei Alexandrescu | Andrei Alexandrescu:
> No. -- Andrei
Yet, experience in D has shown very well that having unsigned lengths is the wrong design choice. It's a D wart.
Bye,
bearophile
|
November 19, 2014 Re: 'int' is enough for 'length' to migrate code from x86 to x64 | ||||
---|---|---|---|---|
| ||||
Posted in reply to Andrei Alexandrescu | Andrei Alexandrescu: > There are related bugs in Java too, e.g. I remember one in binary search where (i + j) / 2 was wrong because of an overflow. This is possible in D too. > Also, Java does have a package for unsigned integers so apparently it's necessary. This is irrelevant. No one here is saying that a system language should not have unsigned values. The discussion here is about the type of array lengths. Bye, bearophile |
November 19, 2014 Re: 'int' is enough for 'length' to migrate code from x86 to x64 | ||||
---|---|---|---|---|
| ||||
Posted in reply to bearophile | On Wednesday, 19 November 2014 at 20:40:53 UTC, bearophile wrote:
> Andrei Alexandrescu:
>
>> There are related bugs in Java too, e.g. I remember one in binary search where (i + j) / 2 was wrong because of an overflow.
>
> This is possible in D too.
>
>
>> Also, Java does have a package for unsigned integers so apparently it's necessary.
>
> This is irrelevant. No one here is saying that a system language should not have unsigned values. The discussion here is about the type of array lengths.
>
> Bye,
> bearophile
The only signed types that are able to represent all possible
array lengths on 64 bit systems are long double and cent.
|
November 19, 2014 Re: 'int' is enough for 'length' to migrate code from x86 to x64 | ||||
---|---|---|---|---|
| ||||
Posted in reply to Ary Borenszweig | On Wednesday, 19 November 2014 at 18:09:11 UTC, Ary Borenszweig wrote:
> On 11/19/14, 7:03 AM, Don wrote:
>> On Tuesday, 18 November 2014 at 18:23:52 UTC, Marco Leise wrote:
> >
>> Weird consequence: using subtraction with an unsigned type is nearly
>> always a bug.
>>
>> I wish D hadn't called unsigned integers 'uint'. They should have been
>> called '__uint' or something. They should look ugly. You need a very,
>> very good reason to use an unsigned type.
>>
>> We have a builtin type that is deadly but seductive.
>>
>
> I agree. An array's length makes sense as an unsigned ("an array can't have a negative length, right?") but it leads to the bugs you say. For example:
>
> ~~~
> import std.stdio;
>
> void main() {
> auto a = [1, 2, 3];
> auto b = [1, 2, 3, 4];
> if (a.length - b.length > 0) {
> writeln("Can you spot the bug that easily?");
> }
> }
> ~~~
>
> Yes, it makes sense, but at the same time it leads to super unintuitive math operations being involved.
>
> Rust made the same mistake and now a couple of times I've seen bugs like these being reported. Never seen them in Java or .Net though. I wonder why...
IMO array length should be unsigned but I'd like to see unsafe operators on unsigned types illegal. It is trivial to write (a.signed - b.signed) and it should be explicit in the code, i.e. not something that the compiler will do automatically behind the scenes.
Cheers,
uri
|
Copyright © 1999-2021 by the D Language Foundation