November 19, 2014
On Tuesday, 18 November 2014 at 18:23:52 UTC, Marco Leise wrote:
> Mixed arithmetics decay to unsinged anyways and you don't need checks like `assert(idx >= 0)`.

What such assert gets you, what bound checking doesn't?
November 19, 2014
On Wednesday, 19 November 2014 at 10:03:35 UTC, 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.

int has wrapping the same semantics too, only it wraps to negative numbers instead of zero. If you insist on non-wrapping length, it should return double or long double.
November 19, 2014
On Wednesday, 19 November 2014 at 11:04:05 UTC, Matthias Bentrup wrote:
> On Wednesday, 19 November 2014 at 10:03:35 UTC, 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.
>
> int has wrapping the same semantics too, only it wraps to negative numbers instead of zero. If you insist on non-wrapping length, it should return double or long double.

Which would be totally wrong for different reasons.

Short of BigInts or overflow-checking, there is no perfect option.

An overflow-checked type that could be reasonably well optimised would be nice, as mentioned by bearophile many times.
November 19, 2014
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. and it doesn't matter what king of integer is used if you didn't fail your sanity checks.

> 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.
you just named all of built-in types. ah, and rename all keywords too, they far too dangerous.


November 19, 2014
On Wednesday, 19 November 2014 at 11:43:38 UTC, John Colvin wrote:
> On Wednesday, 19 November 2014 at 11:04:05 UTC, Matthias Bentrup wrote:
>> On Wednesday, 19 November 2014 at 10:03:35 UTC, 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.
>>
>> int has wrapping the same semantics too, only it wraps to negative numbers instead of zero.

No. Signed types do not *wrap*. They *overflow* if their range is exceeded.
This is not the same thing. Overflow is always an error.
And the compiler could insert checks to detect this.

That's not possible for unsigned types. With an unsigned type, wrapping is part of the semantics.

Moreover, hitting an overflow with a signed type is an exceptional situation. Wrapping with an unsigned type is entirely normal, and happens with things like 2u - 1u.

>If you insist on
>> non-wrapping length, it should return double or long double.
>
> Which would be totally wrong for different reasons.
>
> Short of BigInts or overflow-checking, there is no perfect option.
>
> An overflow-checked type that could be reasonably well optimised would be nice, as mentioned by bearophile many times.

I don't think we need to worry about the pathological cases. The problem with unsigned size_t is that it introduces inappropriate semantics everywhere for the sake of the pathological cases.

IMHO the correct solution is to say that the length of a slice cannot exceed half of the memory space, otherwise a runtime error will occur. And then make size_t a positive integer.

Then let typeof(size_t - size_t) == int, instead of uint. All other operations stay as size_t.

Perhaps we can get most of the way, by improving range propagation.


November 19, 2014
On Wed, 19 Nov 2014 13:33:21 +0000
Don via Digitalmars-d <digitalmars-d@puremagic.com> wrote:

> No. Signed types do not *wrap*. They *overflow* if their range is exceeded.
same for unsigned ints.

> This is not the same thing. Overflow is always an error. And the compiler could insert checks to detect this.
and for unsigned ints. i want compilers to has special code for this. something like `checkedInt(...)`. and this must be built-in, 'cause checking carry flag is cheap, but can be done only on "machine" level.

> That's not possible for unsigned types. With an unsigned type, wrapping is part of the semantics.
see above.

> Moreover, hitting an overflow with a signed type is an exceptional situation. Wrapping with an unsigned type is entirely normal, and happens with things like 2u - 1u.
having results of unsigned int wrapping defined doesn't mean that it's "normal". it's just *defined*, so you can check for it without triggering UB.

> IMHO the correct solution is to say that the length of a slice cannot exceed half of the memory space, otherwise a runtime error will occur. And then make size_t a positive integer.
but why? maybe 1/3 of address space fits better? or 256 bytes, to really avoid "overflows" and "wrapping"?

> Then let typeof(size_t - size_t) == int, instead of uint. All other operations stay as size_t.
check and cast. you can check length and then safely cast it to int, no probs.


November 19, 2014
On Tuesday, 18 November 2014 at 18:03:35 UTC, ketmar via Digitalmars-d wrote:
> On Tue, 18 Nov 2014 17:59:04 +0000
> David Eagen via Digitalmars-d <digitalmars-d@puremagic.com> wrote:
>
>> Isn't the purpose of size_t is to be large enough to address all available memory? A negative value is not only too small but doesn't make sense when discussing lengths.
>> 
>> Correctness requires using size_t.
> yes. besides, there is no such thing as "negative length", so it's
> somewhat... weird to use signed integer for length.

A length can certainly be negative. Just as a bank balance can be negative. It's just a number.

If I have two pencils of length 10 cm and 15 cm, then the first one is -5 cm longer than the other.

Of course any physical pencil is always of positive length, but that doesn't mean that typeof(pencil.length) can never be negative.



November 19, 2014
> If I have two pencils of length 10 cm and 15 cm, then the first one is -5 cm longer than the other.
>
> Of course any physical pencil is always of positive length, but that doesn't mean that typeof(pencil.length) can never be negative.

Right.
'int' is easy to use,is enough,and easy to migrate code to 64 bit.
November 19, 2014
On Wed, 19 Nov 2014 13:47:50 +0000
Don via Digitalmars-d <digitalmars-d@puremagic.com> wrote:

> > yes. besides, there is no such thing as "negative length", so
> > it's
> > somewhat... weird to use signed integer for length.
> 
> A length can certainly be negative. Just as a bank balance can be negative. It's just a number.
what is the relation between bank balance and length? please, show me the array with -1 element, so i can see negative length myself.

seems to me that you are using "length" as "quantity", but that isn't right.

> 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! ;-)

> Of course any physical pencil is always of positive length, but that doesn't mean that typeof(pencil.length) can never be negative.
it can't be negative. if it can be negative, it is wrongly named, it's not "length".


November 19, 2014
On Wednesday, 19 November 2014 at 13:47:31 UTC, ketmar via Digitalmars-d wrote:
> On Wed, 19 Nov 2014 13:33:21 +0000
> Don via Digitalmars-d <digitalmars-d@puremagic.com> wrote:
>
>> No. Signed types do not *wrap*. They *overflow* if their range is exceeded.
> same for unsigned ints.
>
>> This is not the same thing. Overflow is always an error.
>> And the compiler could insert checks to detect this.
> and for unsigned ints. i want compilers to has special code for this.
> something like `checkedInt(...)`. and this must be built-in, 'cause
> checking carry flag is cheap, but can be done only on "machine" level.

I don't know what you mean. For unsigned ints, carry is not an error. That's the whole point of unsigned!

> That's not possible for unsigned types. With an unsigned type,
>> wrapping is part of the semantics.
> see above.
>
>> Moreover, hitting an overflow with a signed type is an exceptional situation. Wrapping with an unsigned type is entirely normal, and happens with things like 2u - 1u.
> having results of unsigned int wrapping defined doesn't mean that it's
> "normal". it's just *defined*, so you can check for it without
> triggering UB.
>
>> IMHO the correct solution is to say that the length of a slice cannot exceed half of the memory space, otherwise a runtime error will occur. And then make size_t a positive integer.
> but why? maybe 1/3 of address space fits better? or 256 bytes, to
> really avoid "overflows" and "wrapping"?

No. The point is to get correct semantics. Unsigned types do not have the correct semantics. Signed types do.

>> Then let typeof(size_t - size_t) == int, instead of uint. All other operations stay as size_t.
> check and cast. you can check length and then safely cast it to int, no
> probs.

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).

---
Almost everybody seems to think that unsigned means positive. It does not.
---