Is it true that people write a crazy code with overlapping side effects, while maintaining equanimity?
The order of evaluation of expressions is determined by a particular implementation, except when the language guarantees a certain order of calculations. If, in addition to the result, evaluating the expression causes changes in the runtime, then the expression is said to have side effects.In our internal newsletter about C #, a regular question arises, which concerns the correct interpretation of such constructions:
a -= a *= a;In response, I ask:
p[x++] = ++x;
Yes, who writes such a code with an imperturbable look? It's one thing when you write this, trying to win at the International COC Contest, or if you want to write a puzzle - but in both cases you realize that you are doing something non-standard. That, there really is someone who writes a - = a * = a and p [x ++] = ++ x; and thinks to himself "Shit, yes I write really cool code! "What Eric Lippert answers me:" Yes, such people definitely meet. " As an example, he cited one successful book by a popular author who firmly believed that the shorter the code, the faster it works. So, imagine, the sales of this book are already over 4 million copies and continue to grow. The author of this book tried to cram into each expression several side effects at once, densely dotting them with conditional ternary operators; the whole point is that he sincerely believed that the speed of the program is proportional to the number of semicolons used in it - and that every time a programmer declares a new variable, God kills a puppy.
Of course, with some effort, you can teach the compiler to analyze this code and give a warning like this: " The result of this operation may vary depending on the calculation order ". However, if such a decision is made, you will have to deal with other problems.
First, there will be a large number of false positives. Let's say you write the following code:
total_cost = p->base_price + p->calculate_tax();This code will cause a warning: the compiler will see that the calculate_tax method is not a constant (const), so it is concerned that the method can change the base_price variable - and in this case will be whether you consider the tax at the original base_price the base price, or on the already changed. Now, let's say that you know (and this knowledge is not available to the compiler) that the calculation method calculate_tax updates the value of the local tax variable ( tax ) in the object, but does not change the base price ; so for you this warning will be a false alarm.
As you have already seen, the problem here is that in case of adding such a warning, an awful lot of false alarms await us, as a result of which the developers will simply turn off this warning.
Well, well, we'll take a step back, and let's only warn about the most egregious cases - only when the variable changes and is calculated in the same expression. " Warning: The expression relies on the calculation order ".
Take the super-clever programmer Expert Joe: he knows that his code is flawless, and the compiler is weak. "Well, yes, it's obvious that incrementing a variable is first done, then it is used to calculate the index of the array, and then the result of the search in the array is stored back into the variable. There is no conflict of the order of calculation. Stupid compiler! ". As a result, super-smart programmer Expert Joe will turn off this warning, finding it useless. Well, our Expert Joe is still a hopeless case, and we do not bother with him.
But let's take another programmer, Novice Joe - in fact, he will not even understand the essence of this warning. "Well, ok, let's see. I compiled this function five times, and each time I got the same result. The result looks reliable to me. It seems that the warning was false. " Thus, just those who were supposed to benefit from this warning, do not always have sufficient knowledge to understand it.
Of course, some time passes, and this question pops up again in the mailing list. Someone will necessarily ask why the expression x ^ = y ^ = x ^ = y does not work in C #, although it works in C ++. Here is one more proof that some people still write code that relies on several side effects at once - and these same people sincerely believe that their code is obvious and guaranteed to work.
Link to discussion
|Vote for this post
Bring it to the Main Page