November 21, 2014
On Fri, Nov 21, 2014 at 10:59:13AM -0800, Walter Bright via Digitalmars-d wrote:
> On 11/21/2014 6:03 AM, ketmar via Digitalmars-d wrote:
> >On Thu, 20 Nov 2014 13:28:37 -0800
> >Walter Bright via Digitalmars-d <digitalmars-d@puremagic.com> wrote:
> >
> >>On 11/20/2014 7:52 AM, H. S. Teoh via Digitalmars-d wrote:
> >>>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.
> >>
> >>What about:
> >>
> >>      uint x;
> >>      auto z = x - 1;
> >>
> >>?
> >>
> >here z must be `long`. and for `ulong` compiler must emit error.
> 
> 
> So, any time an integer literal appears in an unsigned expression, the type of the expression becomes signed?

And subtracting two ulongs gives a compile error?! Whoa, that is truly crippled.


T

-- 
Food and laptops don't mix.
November 21, 2014
"Andrei Alexandrescu"  wrote in message news:m4nn38$1lau$2@digitalmars.com...

> What is your point? (Honest question.)

That using signed integers exclusively eliminates one class of bugs, while making another class only marginally more likely.

> Are you proposing that we make all array lengths signed?

No, I think that ship has sailed.  But I recommend avoiding unsigned types for general arithmetic. 

November 21, 2014
On Fri, 21 Nov 2014 10:59:13 -0800
Walter Bright via Digitalmars-d <digitalmars-d@puremagic.com> wrote:

> On 11/21/2014 6:03 AM, ketmar via Digitalmars-d wrote:
> > On Thu, 20 Nov 2014 13:28:37 -0800
> > Walter Bright via Digitalmars-d <digitalmars-d@puremagic.com> wrote:
> >
> >> On 11/20/2014 7:52 AM, H. S. Teoh via Digitalmars-d wrote:
> >>> 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.
> >>
> >> What about:
> >>
> >>       uint x;
> >>       auto z = x - 1;
> >>
> >> ?
> >>
> > here z must be `long`. and for `ulong` compiler must emit error.
> 
> 
> So, any time an integer literal appears in an unsigned expression, the type of the expression becomes signed?
nope. only for `auto` expressions.


November 21, 2014
On Fri, Nov 21, 2014 at 10:57:44AM -0800, Walter Bright via Digitalmars-d wrote:
> On 11/21/2014 10:05 AM, ketmar via Digitalmars-d wrote:
> >why do you believe that i'm not aware of overflows and don't checking for that? i'm used to think about overflows and do overflow checking in production code since my Z80 days. and i don't believe that "infrequent bug" is better than "frequent bug". both are equally bad.
> 
> 
> Having coded with 16 bit computers for decades, one gets used to thinking about and dealing with overflows :-)

I used to write 8-bit assembly code on the 6502 (yeah I'm so dating myself), where overflows and underflows happen ALL THE TIME. :-) In fact, they happen so much, that I learned to embrace modulo arithmetic instead of fearing it. I would take advantage of value wrapping to shave off a few cycles here and a few cycles there -- they do add up, given that the CPU only ran at a meager 1MHz, so every little bit counts.

Then in the 16-bit days, I wrote a sliding-window buffer using a 64kB buffer where the wraparound of the 16-bit index variable was a feature rather than a bug. :-)  Basically, once it reaches within a certain distance from the end of the window, the next 32kB block of data was paged in from disk into the other half of the buffer, so as long as the operation didn't span more than 32kB each time, you can just increment the 16-bit index without needing to check for the end of the buffer -- it'd automatically wrap around to the beginning where the new 32kB block has been loaded once you go past the end. A truly circular buffer! :-P


T

-- 
That's not a bug; that's a feature!
November 21, 2014
Am Wed, 19 Nov 2014 21:38:50 +0000
schrieb "Matthias Bentrup" <matthias.bentrup@googlemail.com>:

> array lengths on 64 bit systems are long double and cent.

Last time I checked, null was a reserved address. ;)

-- 
Marco

November 21, 2014
On 11/21/2014 11:36 AM, ketmar via Digitalmars-d wrote:
> On Fri, 21 Nov 2014 10:59:13 -0800
> Walter Bright via Digitalmars-d <digitalmars-d@puremagic.com> wrote:
>
>> On 11/21/2014 6:03 AM, ketmar via Digitalmars-d wrote:
>>> On Thu, 20 Nov 2014 13:28:37 -0800
>>> Walter Bright via Digitalmars-d <digitalmars-d@puremagic.com> wrote:
>>>
>>>> On 11/20/2014 7:52 AM, H. S. Teoh via Digitalmars-d wrote:
>>>>> 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.
>>>>
>>>> What about:
>>>>
>>>>        uint x;
>>>>        auto z = x - 1;
>>>>
>>>> ?
>>>>
>>> here z must be `long`. and for `ulong` compiler must emit error.
>>
>>
>> So, any time an integer literal appears in an unsigned expression, the type of
>> the expression becomes signed?
> nope. only for `auto` expressions.
>

So 'auto' has different type rules for expressions than anywhere else in D?

Consider:

    void foo(T)(T a) { ... }

    if (x - 1) foo(x - 1);
    if (auto a = x - 1) foo(a);

and now foo() is instantiated with a different type?

I'm afraid I can't sell that to anyone :-(
November 21, 2014
Am Thu, 20 Nov 2014 07:42:20 +0000
schrieb "FrankLike" <1150015857@qq.com>:

> > That I partially, fractionally even, agree with. We agonized for a long time about what to do to improve on the state of the art back in 2007 - literally months I recall. Part of the conclusion was that reverting to int for object lengths would be a net negative.
> >
> > Andrei
> 
> All of these discussions, let me known how to do about 'length',D better than c,it's a system language.
> 
> For WindowsAPI: cast(something)length ,and other modify it to size_t.
> 
> Thank you all.

The correct thing is to use for WindowsAPI: length.to!int It checks if the length actually fits into an int.

-- 
Marco

November 21, 2014
On Fri, 21 Nov 2014 11:52:29 -0800
Walter Bright via Digitalmars-d <digitalmars-d@puremagic.com> wrote:

> So 'auto' has different type rules for expressions than anywhere else in D?
> 
> Consider:
> 
>      void foo(T)(T a) { ... }
> 
>      if (x - 1) foo(x - 1);
>      if (auto a = x - 1) foo(a);
> 
> and now foo() is instantiated with a different type?
> 
> I'm afraid I can't sell that to anyone :-(
the whole thing of `auto` is to let compiler decide. i won't be surprised if `a` becomes 80-bit real or bigint here -- that's up to compiler to decide which type will be able to hold the whole range. `auto` for me means "i don't care what type you'll choose, just do it for me and don't lose any bits." this can be some kind of structure with overloaded operators, for example.


November 21, 2014
Am Fri, 21 Nov 2014 11:24:37 +0000
schrieb "bearophile" <bearophileHUGS@lycos.com>:

> Walter Bright:
> 
> > I thought everyone hated foreach_reverse!
> 
> I love it!
> 
> Bye,
> bearophile

Hey, it is a bit ugly, but I'd pick

foreach_reverse (i; 0 .. length)

anytime over

import std.range;
foreach (i; iota(length).retro())

-- 
Marco

November 21, 2014
On 11/21/2014 7:36 AM, Don wrote:
> On Friday, 21 November 2014 at 04:53:38 UTC, Walter Bright wrote:
>> 0 crossing bugs tend to show up much sooner, and often immediately.
>
>
> You're missing the point here. The problem is that people are using 'uint' as if
> it were a positive integer type.
>
> Suppose  D had a type 'natint', which could hold natural numbers in the range
> 0..uint.max.  Sounds like 'uint', right? People make the mistake of thinking
> that is what uint is. But it is not.
>
> How would natint behave, in the type system?
>
> typeof (natint - natint)  ==  int     NOT natint  !!!
>
> This would of course overflow if the result is too big to fit in an int. But the
> type would be correct.  1 - 2 == -1.
>
> But
>
> typeof (uint - uint ) == uint.
>
> The bit pattern is identical to the other case. But the type is wrong.
>
> It is for this reason that uint is not appropriate as a model for positive
> integers. Having warnings about mixing int and uint operations in relational
> operators is a bit misleading, because mixing signed and unsigned is not usually
> the real problem. Instead, those warnings a symptom of a type system mistake.
>
> You are quite right in saying that with a signed length, overflows can still
> occur. But, those are in principle detectable. The compiler could add runtime
> overflow checks for them, for example. But the situation for unsigned is not
> fixable, because it is a problem with the type system.
>
>
> By making .length unsigned, we are telling people that if .length is
> used in a subtraction expression, the type will be wrong.
>
> It is the incorrect use of the type system that is the underlying problem.

I believe I do understand the problem. As a practical matter, overflow checks are not going to be added for performance reasons. Also, in principle, uint-uint can generate a runtime check for underflow (i.e. the carry flag).