View mode: basic / threaded / horizontal-split · Log in · Help
June 04, 2012
Increment / Decrement Operator Behavior
The increment and decrement operators are highly dependent on 
operator precedence and associativity. If the actions are 
performed in a different order than the developer presumed, it 
could cause unexpected behavior.

I had a simple idea to change the behavior of this operator. It 
works for the postfix operators but not prefix. Take the 
following code:

size_t i = 5;
writeln(i--, i--, i--);

As of now, this writes "543". With my idea, instead it would 
write, "555". Under the hood, the compiler would rewrite the code 
as:

size_t i = 5;
writeln(i, i, i);
--i;
--i;
--i;

It decrements the variable after the current statement. While not 
the norm, this behavior is at least predictable. For non-static 
variables, such as array elements, the compiler could store a 
temporary reference to the variable so it can decrement it 
afterwards.

I'm not actually proposing we actually make this change. I simply 
thought it was a nifty idea worth sharing.
June 04, 2012
Re: Increment / Decrement Operator Behavior
On Mon, 04 Jun 2012 20:36:14 +0200, Xinok <xinok@live.com> wrote:

> The increment and decrement operators are highly dependent on operator  
> precedence and associativity. If the actions are performed in a  
> different order than the developer presumed, it could cause unexpected  
> behavior.
>
> I had a simple idea to change the behavior of this operator. It works  
> for the postfix operators but not prefix. Take the following code:
>
> size_t i = 5;
> writeln(i--, i--, i--);
>
> As of now, this writes "543". With my idea, instead it would write,  
> "555". Under the hood, the compiler would rewrite the code as:
>
> size_t i = 5;
> writeln(i, i, i);
> --i;
> --i;
> --i;
>
> It decrements the variable after the current statement. While not the  
> norm, this behavior is at least predictable. For non-static variables,  
> such as array elements, the compiler could store a temporary reference  
> to the variable so it can decrement it afterwards.
>
> I'm not actually proposing we actually make this change. I simply  
> thought it was a nifty idea worth sharing.

If I ever saw a construct like that, I would certainly test how that  
works, then rewrite it.
I wouldn't find it natural with the new behavior either. I would expect  
"543" or "345".
How often do you come across code like that? I think it's an anti-pattern,  
and shouldn't be encouraged even if it was easier to understand.
June 04, 2012
Re: Increment / Decrement Operator Behavior
If you find yourself using postfix increment/decrement operators 
in the same function call in multiple arguments, slap yourself 
firmly in the face and refactor that code.
June 04, 2012
Re: Increment / Decrement Operator Behavior
On Mon, 04 Jun 2012 20:57:11 +0200, simendsjo <simendsjo@gmail.com> wrote:

> On Mon, 04 Jun 2012 20:36:14 +0200, Xinok <xinok@live.com> wrote:
>
>> The increment and decrement operators are highly dependent on operator  
>> precedence and associativity. If the actions are performed in a  
>> different order than the developer presumed, it could cause unexpected  
>> behavior.
>>
>> I had a simple idea to change the behavior of this operator. It works  
>> for the postfix operators but not prefix. Take the following code:
>>
>> size_t i = 5;
>> writeln(i--, i--, i--);
>>
>> As of now, this writes "543". With my idea, instead it would write,  
>> "555". Under the hood, the compiler would rewrite the code as:
>>
>> size_t i = 5;
>> writeln(i, i, i);
>> --i;
>> --i;
>> --i;
>>
>> It decrements the variable after the current statement. While not the  
>> norm, this behavior is at least predictable. For non-static variables,  
>> such as array elements, the compiler could store a temporary reference  
>> to the variable so it can decrement it afterwards.
>>
>> I'm not actually proposing we actually make this change. I simply  
>> thought it was a nifty idea worth sharing.
>
> If I ever saw a construct like that, I would certainly test how that  
> works, then rewrite it.
> I wouldn't find it natural with the new behavior either. I would expect  
> "543" or "345".
> How often do you come across code like that? I think it's an  
> anti-pattern, and shouldn't be encouraged even if it was easier to  
> understand.

Oh, and what should writeln(i++, ++i, ++i, i++) do?

It is messy whatever the logic implementation.
June 04, 2012
Re: Increment / Decrement Operator Behavior
On Monday, 4 June 2012 at 20:08:57 UTC, simendsjo wrote:
> Oh, and what should writeln(i++, ++i, ++i, i++) do?
>
> It is messy whatever the logic implementation.

For prefix operators, it would be logical to perform the action 
before the statement, such as the code would be rewritten as:

++i
++i
writeln(i, i, i, i)
i++
i++

However, I already stated that it wouldn't work for prefix 
operators. Take this statement:

++foo(++i)

There's no way to increment the return value of foo without 
calling foo first. This "logic" would only work for the postfix 
operators.

I came up with the idea after refactoring this code:
https://github.com/Xinok/XSort/blob/master/timsort.d#L111

Each call to mergeAt is followed by --stackLen. I could have used 
stackLen-- in the mergeAt statement instead, but I didn't want to 
rely on operator precedence for the correct behavior.
June 04, 2012
Re: Increment / Decrement Operator Behavior
Bernard Helyer:

> If you find yourself using postfix increment/decrement 
> operators in the same function call in multiple arguments, slap 
> yourself firmly in the face and refactor that code.

I think this is not acceptable, you can't rely on that, future D 
programers will not slap themselves and refactor their code. Some 
of the acceptable alternatives are:
1) Make post/pre increments return void. This avoid those 
troubles. I think Go language has chosen this. This is my 
preferred solution.
2) Turn that code into a syntax error for some other cause.
3) Design the language so post/pre increments give a defined 
effect on all D compilers on all CPUs. Walter since lot of time 
says this is planned for D. This leads to deterministic programs, 
but sometimes they are hard to understand and hard to translate 
(port) to other languages any way. Translating code to other 
languages is not irrelevant because D must be designed to make it 
easy to understand the semantics of the code.

Bye,
bearophile
June 04, 2012
Re: Increment / Decrement Operator Behavior
On Monday, 4 June 2012 at 20:44:42 UTC, bearophile wrote:
> Bernard Helyer:
>
>> If you find yourself using postfix increment/decrement 
>> operators in the same function call in multiple arguments, 
>> slap yourself firmly in the face and refactor that code.
>
> I think this is not acceptable, you can't rely on that, future 
> D programers will not slap themselves and refactor their code. 
> Some of the acceptable alternatives are:
> 1) Make post/pre increments return void. This avoid those 
> troubles. I think Go language has chosen this. This is my 
> preferred solution.
> 2) Turn that code into a syntax error for some other cause.
> 3) Design the language so post/pre increments give a defined 
> effect on all D compilers on all CPUs. Walter since lot of time 
> says this is planned for D. This leads to deterministic 
> programs, but sometimes they are hard to understand and hard to 
> translate (port) to other languages any way. Translating code 
> to other languages is not irrelevant because D must be designed 
> to make it easy to understand the semantics of the code.
>
> Bye,
> bearophile

If people can't be bothered to understand what they write, they 
can go hang.
June 04, 2012
Re: Increment / Decrement Operator Behavior
On Monday, June 04, 2012 23:22:26 Bernard Helyer wrote:
> On Monday, 4 June 2012 at 20:44:42 UTC, bearophile wrote:
> > Bernard Helyer:
> >> If you find yourself using postfix increment/decrement
> >> operators in the same function call in multiple arguments,
> >> slap yourself firmly in the face and refactor that code.
> > 
> > I think this is not acceptable, you can't rely on that, future
> > D programers will not slap themselves and refactor their code.
> > Some of the acceptable alternatives are:
> > 1) Make post/pre increments return void. This avoid those
> > troubles. I think Go language has chosen this. This is my
> > preferred solution.
> > 2) Turn that code into a syntax error for some other cause.
> > 3) Design the language so post/pre increments give a defined
> > effect on all D compilers on all CPUs. Walter since lot of time
> > says this is planned for D. This leads to deterministic
> > programs, but sometimes they are hard to understand and hard to
> > translate (port) to other languages any way. Translating code
> > to other languages is not irrelevant because D must be designed
> > to make it easy to understand the semantics of the code.
> > 
> > Bye,
> > bearophile
> 
> If people can't be bothered to understand what they write, they
> can go hang.

I think that Bernard is being a bit harsh, but in essence, I agree. Since the 
evaluation order of arguments is undefined, programmers should be aware of that 
and code accordingly. If they don't bother to learn, then they're going to get 
bitten, and that's life.

Now, Walter _has_ expressed interest in changing it so that the order of 
evaluation for function arguments is fully defined as being left-to-right, 
which solves the issue. I'd still council against getting into the habit of 
writing code which relies on the order of evaluation for the arguments to a 
function, since it's so common for other languages not to define it (so that 
the compiler can better optimize the calls), and so getting into the habit of 
writing code which _does_ depend on the order of evalution for function 
arguments will cause you to write bad code you when you work in most other
programming languages.

As for treating pre or post-increment operators specially in some manner, that 
doesn't make sense. The problem is far more general than that. If we're going 
to change anything, it would be to make it so that the language itself defines 
the order of evaluation of function arguments as being left-to-right.

- Jonathan M Davis
June 05, 2012
Re: Increment / Decrement Operator Behavior
Jonathan M Davis:

> If they don't bother to learn, then they're going to get 
> bitten, and that's life.

A modern language must try to avoid common programmer mistakes, 
where possible (like in this case).


> As for treating pre or post-increment operators specially in 
> some manner, that
> doesn't make sense. The problem is far more general than that. 
> If we're going
> to change anything, it would be to make it so that the language 
> itself defines
> the order of evaluation of function arguments as being 
> left-to-right.

Probably I have expressed myself badly there, sorry. I'd like to 
see function calls fixed as Walter has stated.
And regarding pre/post de/increment operators, I find them handy, 
but I have seen _so much_ C/C++ code that abuses them that maybe 
I'd like them to return void, as in Go.

Bye,
bearophile
June 05, 2012
Re: Increment / Decrement Operator Behavior
On Monday, 4 June 2012 at 20:44:42 UTC, bearophile wrote:
> 1) Make post/pre increments return void. This avoid those 
> troubles. I think Go language has chosen this. This is my 
> preferred solution.
I wonder in that case, is it even worth including in the 
language? For me anyways, the whole point of these operators is 
to use them in expressions. Otherwise, why not simply write 
(i+=1)?
« First   ‹ Prev
1 2
Top | Discussion index | About this forum | D home