November 19, 2014
On Wed, 19 Nov 2014 14:04:15 +0000
Don via Digitalmars-d <digitalmars-d@puremagic.com> wrote:

> I don't know what you mean. For unsigned ints, carry is not an error. That's the whole point of unsigned!
this *may* be not a error. it depends of what programmer wants.

> This is the job of the compiler, not the programmer. The compiler should do this at all possible places where a slice could exceed the int.max / long.max. That's cheap because there are hardly any places it could happen (for example, for array slices it can only happen with 1-byte types).
i, for myself, don't want the compiler to do arcane type conversions behind my back.

> ---
> Almost everybody seems to think that unsigned means positive. It does not.
> ---
sure, it includes zero, which is neither positive nor negative. ;-)


November 19, 2014
On Wednesday, 19 November 2014 at 14:04:16 UTC, Don wrote:
> No. The point is to get correct semantics. Unsigned types do not have the correct semantics. Signed types do.
>

In D both signed and unsigned integers have defined wrapping semantincs. In C++ signed integers are allowed to format your harddisk on overflow.
November 19, 2014
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.
November 19, 2014
David Gileadi:

>     writefln("%s", b.length - a.length);  // Yup, 2
>     writefln("%s", a.length - b.length);  // WAT? 18446744073709551614

Nowadays a better way to write such kind of code is using the Phobos "signed" function:

writefln("%s", b.length.signed - a.length.signed);
writefln("%s", a.length.signed - b.length.signed);


> This is why I agree with Don that:
>
> > Having arr.length return an unsigned type, is a dreadful
> language mistake.

This mistake is by design. Walter has resisted several times turning them into signed values, and even making size_t a type strongly different from uint/ulong. I don't agree with this design decision, but it's unlikely that Walter has changed his mind on it. So better to go on and discuss other things more likely to happen.

Bye,
bearophile
November 19, 2014
On Wed, 19 Nov 2014 09:02:49 -0700
David Gileadi via Digitalmars-d <digitalmars-d@puremagic.com> 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.
ah, let range checking catch that. sure, there are edge cases where range checking fails, but not so many.

besides, overflows are possible with signed ints too, so what signed length does is simply hiding the bad code. any code reviewer must ring a bell when he sees length subtraction without prior checking, be it signed or unsigned. so there is no reason in negative lengthes anyway.


November 19, 2014
On 11/19/14, 9:12 AM, bearophile wrote:
> David Gileadi:
>
>>     writefln("%s", b.length - a.length);  // Yup, 2
>>     writefln("%s", a.length - b.length);  // WAT? 18446744073709551614
>
> Nowadays a better way to write such kind of code is using the Phobos
> "signed" function:
>
> writefln("%s", b.length.signed - a.length.signed);
> writefln("%s", a.length.signed - b.length.signed);

But this requires the following knowledge:
1. That the signed function exists, and its location. As a casual D programmer I didn't know about it.
2. That there's a need for it at all, which requires knowing that length is unsigned. I did know this, but I bet in the heat of programming I'd easily forget it. In a semi-complex algorithm the bug could easily hide for a long time before biting.

>> This is why I agree with Don that:
>>
>> > Having arr.length return an unsigned type, is a dreadful
>> language mistake.
>
> This mistake is by design. Walter has resisted several times turning
> them into signed values, and even making size_t a type strongly
> different from uint/ulong. I don't agree with this design decision, but
> it's unlikely that Walter has changed his mind on it. So better to go on
> and discuss other things more likely to happen.

Yes, I bet you're right about the likelihood of change.
November 19, 2014
David Gileadi:

> But this requires the following knowledge:
> 1. That the signed function exists, and its location. As a casual D programmer I didn't know about it.
> 2. That there's a need for it at all, which requires knowing that length is unsigned. I did know this, but I bet in the heat of programming I'd easily forget it. In a semi-complex algorithm the bug could easily hide for a long time before biting.

A solution for similar language design traps/mistakes is static analysis, with tools like Dscanner trained to recognize the troubling coding patterns, that should suggest workarounds (or to use better designed languages. But no language is perfect).

Bye,
bearophile
November 19, 2014
On 11/19/14 2:03 AM, Don wrote:
> On Tuesday, 18 November 2014 at 18:23:52 UTC, Marco Leise wrote:
>> Am Tue, 18 Nov 2014 15:01:25 +0000
>> schrieb "Frank Like" <1150015857@qq.com>:
>>
>>> > but now ,'int' is enough for use,not huge and not small,only > enough.
>>> > 'int' is easy to write,and most people are used to it.
>>> > Most importantly easier to migrate code,if  'length''s return
>>> >value type is 'int'.
>>>
>>> How about your idea?
>>
>> I get the idea of a broken record right now...
>> Clearly size_t (which I tend to alias with ℕ in my code for
>> brevity and coolness) can express more than 2^31-1 items, which
>> is appropriate to reflect the increase in usable memory per
>> application on 64-bit platforms. Yes, the 64-bit version of a
>> program or library can handle larger data sets. Just like it
>> was when people transitioned from 16-bit to 32-bit. I wont use
>> `int` just because the technically correct thing is `size_t`,
>> even it it is a little harder to type.
>
> This is difficult. Having arr.length return an unsigned type, is a
> dreadful language mistake.
>
>> Aside from the size factor, I personally prefer unsigned types
>> for countable stuff like array lengths. Mixed arithmetics
>> decay to unsinged anyways and you don't need checks like
>> `assert(idx >= 0)`. It is a matter of taste though and others
>> prefer languages with no unsigned types at all.
>
>
> 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.
>
> 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 this applies to C and C++. Not quite to D. -- Andrei

November 19, 2014
ketmar:

> ah, let range checking catch that.

No thanks, I prefer to not have bugs in the first place.


> besides, overflows are possible with signed ints too,

From my experience in coding in D they are far more unlikely than sign-related bugs of array lengths.


> so what signed length does is simply hiding the bad code.

Signed lengths avoids traps that are quite easy to fall into.


> any code reviewer must ring
> a bell when he sees length subtraction without prior checking,
> be it signed or unsigned.

The unsigned nature of array lengths is more tricky than that. They cause troubles even if you just compare (with <) a length with a signed value.

Bye,
bearophile
November 19, 2014
On 11/19/14 6:04 AM, Don wrote:
> Almost everybody seems to think that unsigned means positive. It does not.

That's an exaggeration. With only a bit of care one can use D's unsigned types for positive numbers. Please let's not reduce the matter to black and white.

Andrei