November 20, 2014
On 11/20/14, 5:02 AM, Walter Bright wrote:
> On 11/19/2014 5:03 PM, H. S. Teoh via Digitalmars-d wrote:
>> If this kind of unsafe mixing wasn't allowed, or required explict casts
>> (to signify "yes I know what I'm doing and I'm prepared to face the
>> consequences"), I suspect that bearophile would be much happier about
>> this issue. ;-)
>
> Explicit casts are worse than the problem - they can easily cause bugs.
>
> As for me personally, I like having a complete set of signed and
> unsigned integral types at my disposal. It's like having a full set of
> wrenches that are open end on one end and boxed on the other :-) Most of
> the time either end will work, but sometimes only one will.
>
> Now, if D were a non-systems language like Basic, Go or Java, unsigned
> types could be reasonably dispensed with. But D is a systems programming
> language, and it ought to have available types that match what the
> hardware supports.
>

Nobody is saying to remove unsigned types from the language. They have their uses. It's just that using them for an array's length leads to subtle bugs. That's all.
November 20, 2014
On 11/20/14 6:20 AM, Ary Borenszweig wrote:
> On 11/20/14, 6:47 AM, Andrei Alexandrescu wrote:
>> On 11/20/14 12:18 AM, Don wrote:
>>> On Wednesday, 19 November 2014 at 17:55:26 UTC, Andrei Alexandrescu
>>> wrote:
>>>> 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
>>>
>>> Even in the responses in this thread indicate that about half of the
>>> people here don't understand unsigned.
>>>
>>> "unsigned" means "I want to use modulo 2^^n arithmetic". It does not
>>> mean, "this is an integer which cannot be negative".
>>>
>>> Using modulo 2^^n arithmetic is *weird*. If you are using uint/ulong to
>>> represent a non-negative integer, you are using the incorrect type.
>>>
>>>> "With only a bit of care one can use D's unsigned types for positive
>>>> numbers."
>>>
>>> I do not believe that that statement to be true. I believe that bugs
>>> caused by unsigned calculations are subtle and require an extraordinary
>>> level of diligence. I showed an example at DConf, that I had found in
>>> production code.
>>>
>>> It's particularly challenging in D because of the widespread use of
>>> 'auto':
>>>
>>> auto x = foo();
>>> auto y = bar();
>>> auto z = baz();
>>>
>>> if (x - y > z) { ... }
>>>
>>>
>>> This might be a bug, if one of these functions returns an unsigned
>>> type.  Good luck finding that. Note that if all functions return
>>> unsigned, there isn't even any signed-unsigned mismatch.
>>>
>>> I believe the correct statement, is "With only a bit of care one can use
>>> D's unsigned types for positive numbers and believe that one's code is
>>> correct, even though it contains subtle bugs."
>>
>> Well I'm sorry but I quite disagree. -- Andrei
>>
>
> I don't think disagreeing without a reason (like the one Don gave above)
> is good.

Most of the statements I disagreed with were opinions.

>>> "unsigned" means "I want to use modulo 2^^n arithmetic". It does
>>> not mean, "this is an integer which cannot be negative".

Opinion.

>>> Using modulo 2^^n arithmetic is *weird*.

Opinion.

>>> If you are using
>>> uint/ulong to represent a non-negative integer, you are using the
>>> incorrect type.

Opinion.

>>> I believe that
>>> bugs caused by unsigned calculations are subtle and require an
>>> extraordinary level of diligence.

Opinion (correctly qualified as belief).


Andrei

November 20, 2014
On Thursday, 20 November 2014 at 00:08:08 UTC, Andrei Alexandrescu wrote:
>
> I think we're in good shape with unsigned.

I'd actually prefer signed.  Index-based algorithms can be tricky to write correctly with unsigned index values.  The reason size_t is unsigned in Druntime is because I felt that half the memory range on 32-bit was potentially too small a maximum size in a systems language, and it's unsigned on 64-bit for the sake of consistency.
November 20, 2014
> Most of the statements I disagreed with were opinions.
>
>>>> "unsigned" means "I want to use modulo 2^^n arithmetic". It does
>>>> not mean, "this is an integer which cannot be negative".
>
> Opinion.
>
>>>> Using modulo 2^^n arithmetic is *weird*.
>
> Opinion.
>
>>>> If you are using
>>>> uint/ulong to represent a non-negative integer, you are using the
>>>> incorrect type.
>
> Opinion.
>
>>>> I believe that
>>>> bugs caused by unsigned calculations are subtle and require an
>>>> extraordinary level of diligence.
>
> Opinion (correctly qualified as belief).

It's not only his "opinion", it's his *experience* and if we want
to play the "argument by authority" game: he most likely wrote
more production quality code in D than you did.

Here are some more "opinions":
http://critical.eschertech.com/2010/04/07/danger-unsigned-types-used-here/
November 20, 2014
On Thu, Nov 20, 2014 at 12:02:42AM -0800, Walter Bright via Digitalmars-d wrote:
> On 11/19/2014 5:03 PM, H. S. Teoh via Digitalmars-d wrote:
> >If this kind of unsafe mixing wasn't allowed, or required explict casts (to signify "yes I know what I'm doing and I'm prepared to face the consequences"), I suspect that bearophile would be much happier about this issue. ;-)
> 
> Explicit casts are worse than the problem - they can easily cause bugs.

Not any worse bugs than are currently *silently accepted* by the compiler!


> As for me personally, I like having a complete set of signed and unsigned integral types at my disposal. It's like having a full set of wrenches that are open end on one end and boxed on the other :-) Most of the time either end will work, but sometimes only one will.
> 
> Now, if D were a non-systems language like Basic, Go or Java, unsigned types could be reasonably dispensed with. But D is a systems programming language, and it ought to have available types that match what the hardware supports.

Please note that I never suggested anywhere that we get rid of unsigned types. In fact, I think it was a right decision to include unsigned types in the language and to use an unsigned type for array length.

What *could* be improved, is the prevention of obvious mistakes in *mixing* signed and unsigned types. Right now, D allows code like the following with no warning:

	uint x;
	int y;
	auto z = x - y;

BTW, this one is the same in essence as an actual bug that I fixed in druntime earlier this year, so downplaying it as a mistake people make 'cos they confound computer math with math math is fallacious.


T

-- 
He who laughs last thinks slowest.
November 20, 2014
On Thu, Nov 20, 2014 at 11:22:00AM -0300, Ary Borenszweig via Digitalmars-d wrote:
> On 11/20/14, 5:02 AM, Walter Bright wrote:
[...]
> >As for me personally, I like having a complete set of signed and unsigned integral types at my disposal. It's like having a full set of wrenches that are open end on one end and boxed on the other :-) Most of the time either end will work, but sometimes only one will.
> >
> >Now, if D were a non-systems language like Basic, Go or Java, unsigned types could be reasonably dispensed with. But D is a systems programming language, and it ought to have available types that match what the hardware supports.
> >
> 
> Nobody is saying to remove unsigned types from the language. They have their uses. It's just that using them for an array's length leads to subtle bugs.  That's all.

Using unsigned types for array length doesn't necessarily lead to subtle bugs, if the language was stricter about mixing signed and unsigned values.


T

-- 
Recently, our IT department hired a bug-fix engineer. He used to work for Volkswagen.
November 20, 2014
On Thu, Nov 20, 2014 at 08:18:23AM +0000, Don via Digitalmars-d wrote:
> On Wednesday, 19 November 2014 at 17:55:26 UTC, Andrei Alexandrescu wrote:
> >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
> 
> Even in the responses in this thread indicate that about half of the people here don't understand unsigned.
> 
> "unsigned" means "I want to use modulo 2^^n arithmetic". It does not mean, "this is an integer which cannot be negative".
> 
> Using modulo 2^^n arithmetic is *weird*. If you are using uint/ulong to represent a non-negative integer, you are using the incorrect type.
[...]

By that logic, using an int to represent an integer is also using the incorrect type, because a signed type is *also* subject to module 2^^n arithmetic -- just a different form of it where the most negative value wraps around to the most positive values.  Fixed-width integers in computing are NOT the same thing as unrestricted integers in mathematics. No matter how you try to rationalize it, as long as you use hardware fix-width "integers", you're dealing with modulo arithmetic in one form or another. Pretending you're not, is the real source of said subtle bugs.


T

-- 
Why waste time learning, when ignorance is instantaneous? -- Hobbes, from Calvin & Hobbes
November 20, 2014
On Thursday, 20 November 2014 at 15:40:40 UTC, Araq wrote:
>> Most of the statements I disagreed with were opinions.
>>
>>>>> "unsigned" means "I want to use modulo 2^^n arithmetic". It does
>>>>> not mean, "this is an integer which cannot be negative".
>>
>> Opinion.
>>
>>>>> Using modulo 2^^n arithmetic is *weird*.
>>
>> Opinion.
>>
>>>>> If you are using
>>>>> uint/ulong to represent a non-negative integer, you are using the
>>>>> incorrect type.
>>
>> Opinion.
>>
>>>>> I believe that
>>>>> bugs caused by unsigned calculations are subtle and require an
>>>>> extraordinary level of diligence.
>>
>> Opinion (correctly qualified as belief).
>
> It's not only his "opinion", it's his *experience* and if we want
> to play the "argument by authority" game: he most likely wrote
> more production quality code in D than you did.
>
> Here are some more "opinions":
> http://critical.eschertech.com/2010/04/07/danger-unsigned-types-used-here/

My experience is totally the opposite of his. I have been using unsigned for lengths, widths, heights for the past 15 years in C, C++, C# and more recently in D with great success. I don't pretend to be any kind of authority though.
The article you point to is totally flawed and kinda wasteful in terms of having to read it; the very first code snippet is obviously buggy. You can't purposefully write buggy code and then comment on the dangers of this or that!
size_t i;
 for (i = size - 1; i >= 0; --i) {
If you that's subtle to you then yes, use signed!
November 20, 2014
On Thursday, 20 November 2014 at 15:40:40 UTC, Araq wrote:
>> Most of the statements I disagreed with were opinions.
>>
>>>>> "unsigned" means "I want to use modulo 2^^n arithmetic". It does
>>>>> not mean, "this is an integer which cannot be negative".
>>
>> Opinion.
>>
>>>>> Using modulo 2^^n arithmetic is *weird*.
>>
>> Opinion.
>>
>>>>> If you are using
>>>>> uint/ulong to represent a non-negative integer, you are using the
>>>>> incorrect type.
>>
>> Opinion.
>>
>>>>> I believe that
>>>>> bugs caused by unsigned calculations are subtle and require an
>>>>> extraordinary level of diligence.
>>
>> Opinion (correctly qualified as belief).
>
> It's not only his "opinion", it's his *experience* and if we want
> to play the "argument by authority" game: he most likely wrote
> more production quality code in D than you did.

Urrmmm, really? Andrei has written a hell of a lot of production quality code. I use it every day, in production, as do many others.
November 20, 2014
On 11/20/14 7:29 AM, Sean Kelly wrote:
> On Thursday, 20 November 2014 at 00:08:08 UTC, Andrei Alexandrescu wrote:
>>
>> I think we're in good shape with unsigned.
>
> I'd actually prefer signed.  Index-based algorithms can be tricky to
> write correctly with unsigned index values.

The most difficult pattern that comes to mind is the "long arrow" operator seen in backward iteration:

void fun(int[] a)
{
    for (auto i = a.length; i --> 0; )
    {
        // use i
    }
}


Andrei