November 22, 2014
On Fri, 21 Nov 2014 17:45:11 -0800
Andrei Alexandrescu via Digitalmars-d <digitalmars-d@puremagic.com>
wrote:

> On 11/21/14 8:57 AM, ketmar via Digitalmars-d wrote:
> > On Fri, 21 Nov 2014 08:31:13 -0800
> > Andrei Alexandrescu via Digitalmars-d <digitalmars-d@puremagic.com>
> > wrote:
> >
> >> Would you agree that that would break a substantial amount of correct D code? -- Andrei
> > i don't think that code with possible int wrapping and `auto` is correct, so the answer is "no". bad code must be made bad.
> 
> I think you misunderstood the question. -- Andrei
i don't think so. you have two questions here: is such code correct, and will it broke? if the answer to the first question is "no", then the second question has no sense.

i keep thinking that such code is not correct (albeit it compiles ok),
so nothing will break.

at least this is how i understood your question. maybe you are right, and i didn't get it.


November 22, 2014
On 11/21/2014 1:33 PM, Marco Leise wrote:
> As someone using unsigned types all the time, all I need to
> keep in mind are two rules:
>
> 1) Overflow:
>
>    uint number;
> >    number = 10 * number + ch - '0';
>
>    It is handled with:
>    if (number > uint.max / 10)
>    if (number > uint.max - (ch - '0'))

You're better off with core.checkedint here, as not only is it correct, but (eventually) it will enable the compiler to optimize it to simply checking the carry flag.

November 22, 2014
On Fri, 21 Nov 2014 12:35:31 -0800
Walter Bright via Digitalmars-d <digitalmars-d@puremagic.com> wrote:

> 'auto' doesn't mean "break my code if I refactor out expressions into temporaries".
this can be easily avoided: just don't use `auto` for refactoring. i'm still thinking about `auto` as "any type that is able to hold the result". `uint` is obviously not able to hold the result of uint subtraction (as it can be negative, and uint can't). so when compiler automatically chooses the type which can't hold the resulting value, i see this as a design flaw and safety breaking feature.

one of D flaws -- as i can see it -- is trying to be both a reasonably high-level and "close to metal". it's ok for "metal" language to use uint to hold that result and wrap. but it's not ok for high-level language, high-level language should free me of thinking about "wrapping", "overflow" and so on.

i'm not telling that D is bad, i'm simply trying to tell that such confusions will raise again and again. "too far from metal" vs "too close to metal".

i may just not get the whole concept, so i don't know what to expect in such cases. sometimes D amuses me with it's shamelessly breakage of principle of least astonishment. but yet again it very well can be flaw in my brains and not in D.


November 22, 2014
On Saturday, 22 November 2014 at 01:57:05 UTC, Andrei Alexandrescu wrote:
> On 11/21/14 1:55 PM, Marco Leise wrote:
>> Am Wed, 19 Nov 2014 18:20:24 +0000
>> schrieb "Marc Schütz" <schuetzm@gmx.net>:
>>
>>> 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.
>>
>> Now take my position where I explicitly write code relying
>> on the fact that `bigger - smaller` yields correct results.
>>
>> uint bigger = uint.max;
>> uint smaller = 2;
>> if (bigger > smaller)
>> {
>>     auto added = bigger - smaller;
>>     // Now 'added' is an int with the value -3 !
>> }
>> else
>> {
>>     auto removed = smaller - bigger;
>> }
>
> Interesting insight. Thanks for the many analytical examples you're giving in this thread. -- Andrei

It's right.

------smalltest----------------
import std.stdio;
void main()
{
	uint a =100;
	int b =80;
	auto c = a-b;
	auto d = b-a;
	writeln("c is ",c,", c's type is ",typeid(c));
	writeln("d is ",d,", d's type is ",typeid(d));

    auto  e =  b- a;
	writeln("e is ",e," e's type is ",typeid(e));
	auto  f =  cast(int)b- cast(int)a;
	writeln("f is ",f," f's type is ",typeid(f));
}
-------------end-----------------------------
Only c and f's result is ok.



November 22, 2014
On Friday, 21 November 2014 at 09:47:32 UTC, Stefan Koch wrote:
> On Friday, 21 November 2014 at 09:37:50 UTC, Walter Bright wrote:
>> I thought everyone hated foreach_reverse!
>
> I dislike foreach_reverse;
> 1. it's a keyword with an underscore in it;
> 2. complicates implementation of foreach and parsing.
> 3. key_word with under_score

These are compiler implementation issue and all solvable. People don't give a shit about how the compiler work and rightly so. The language is made to fit need of the user, not the needs of the implementer.
November 22, 2014
On Friday, 21 November 2014 at 09:37:50 UTC, Walter Bright wrote:
> On 11/21/2014 12:16 AM, Daniel Murphy wrote:
>> Over the years most of my unsigned-related bugs have been from screwing up
>> various loop conditions.  Thankfully D solves this perfectly with:
>>
>> void fun(int[] a)
>> {
>>    foreach_reverse(i, 0...a.length)
>>    {
>>    }
>> }
>>
>> So I never have to write those again.
>
> I thought everyone hated foreach_reverse!
>
> But, yeah, foreach and ranges+algorithms have virtually eliminated a large category of looping bugs.

Well yeah, it is kind of ugly looking, and a language construct for that when we have retro in phobos...

foreach_reverse is essentially dead weight in the spec.
November 22, 2014
"deadalnix"  wrote in message news:qhirkvbtoiomkyjjugiy@forum.dlang.org...

> These are compiler implementation issue and all solvable. People don't give a shit about how the compiler work and rightly so. The language is made to fit need of the user, not the needs of the implementer.

Usually, although they start to care when the complexity results in a never-ending supply of bugs.  foreach_reverse doesn't come anywhere near this fortunately. 

November 22, 2014
On Friday, 21 November 2014 at 21:44:25 UTC, Marco Leise wrote:
> Am Wed, 19 Nov 2014 18:20:24 +0000
> schrieb "Marc Schütz" <schuetzm@gmx.net>:
>
>> 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.
>
> Now take my position where I explicitly write code relying
> on the fact that `bigger - smaller` yields correct results.
>
> uint bigger = uint.max;
> uint smaller = 2;
> if (bigger > smaller)
> {
>     auto added = bigger - smaller;
>     // Now 'added' is an int with the value -3 !
> }
> else
> {
>     auto removed = smaller - bigger;
> }
>
> In fact checking which value is larger is the only way to
> handle the full result range of subtracting two machine
> integers which is ~2 times larger than what the original type
> can handle:
>
> T.min - T.max .. T.max - T.min
>
> This is one reason why I'd like to just keep working with
> the original unsigned type, but split the range around the
> positive/negative pivot with an if-else.
>
> Implicit conversion of unsigned subtractions to signed values
> would make the above code unnecessarily hard.

Yes, that's true. However, I doubt that this is a common case. I'd say that when two values are to be subtracted (signed or unsigned), and there's no knowledge about which one is larger, it's more useful to get a signed difference. This should be correct in most cases, because I believe it is more likely that the two values are close to each other. It only becomes a problem when they're an opposite sides of the value range.

Unfortunately, no matter how you turn it, there will always be corner cases that a) will be wrong and b) the compiler will allow silently. So the question becomes one of preferences between usefulness for common use cases, ease of detection of errors, and compatibility.
November 22, 2014
On Sat, 22 Nov 2014 03:09:59 +0000
deadalnix via Digitalmars-d <digitalmars-d@puremagic.com> wrote:

> On Friday, 21 November 2014 at 09:47:32 UTC, Stefan Koch wrote:
> > On Friday, 21 November 2014 at 09:37:50 UTC, Walter Bright wrote:
> >> I thought everyone hated foreach_reverse!
> >
> > I dislike foreach_reverse;
> > 1. it's a keyword with an underscore in it;
> > 2. complicates implementation of foreach and parsing.
> > 3. key_word with under_score
> 
> These are compiler implementation issue and all solvable. People don't give a shit about how the compiler work and rightly so. The language is made to fit need of the user, not the needs of the implementer.
`foreach (auto n; ...)` anyone? and `foreach (; ...)`? nope. "cosmetic
changes aren't needed". this is clearly "made for implementer".

luckyly, it's not me who will try explain to newcomers why they has new variable declaration in `foreach` which looks like variable reusing, why they must invent new variable name for each nested `foreach` and so on.

but please, don't tell me about "solvable" -- all this "solvable" only in the sense "make your own fork and fix it. ah, and support your fork. and don't forget that your code cannot be used with vanilla compiler anymore." ok for me, but for others?


November 22, 2014
On Friday, 21 November 2014 at 21:22:55 UTC, Marco Leise wrote:

> Inside opIndex, the unsigned types simplify the range checks
> (by the compiler or explicit) by removing the need to test for
> < 0.
> At the end of the day I find myself using unsigned types much
> more frequently than signed types because I find it easier to
> keep them in check and reason about.

Yes,I think so,except in individual cases.