Ask HN: What would Your_Favorite_Compiler do?
x = 10
y = x + ++x
What is y?
Even the professor who teaches compiler construction at my university thought it was interesting to see how different languages or compilers handle this. I've tried a couple but leave it to you to post and discuss your results.
(I know it's terrible code)
27 comments
[ 3.3 ms ] story [ 63.6 ms ] threadSo in C it's undefined behaviour because the compiler should be permitted to handle it whichever ways it wants, but in perl you'll get 21 as expected.
C is great fun for this - people often expect things like function arguments to be evaluated in the order as written but since it's a low level languages the compiler is allowed to do something completely different if it wants (note this something is still "equivalent" in terms of the C spec, just not in terms of the developer's expectations).
This is one of the many reasons -O3 can make apparently correct code start crashing all over the place.
The poster's question is a classic comp.lang.c "favorite"; misunderstanding operator precedence and the two flavors of incrementing in C.
By the way, the term you're looking for is "binding", and bad languages have a habit of confusing binding and assignment.
LET "binds" its arguments to their corresponding values within its body, in a way identical to function application.
Algebraically his question looks like this:
Where succ is the incrementing, or successor function, and + is the addition function.Btw, much fun can be had with just the increment and decrement functions, along with a predicate to test for zero equality.
http://en.wikipedia.org/wiki/Primitive_recursive_function
P.S. The Lisp "DO" form is for iteration; PROGN and BEGIN are the main block-structure forms used in Common Lisp and Scheme respectively. To the original poster; invest in learning Standard ML and a few lisp dialects, on your own, they will make your compiler hacking far more enjoyable, and you probably wont waste as much time debugging a bad language design from 1970s that thought formal language research from the 1670s was too cutting edge; New Jersey heard "Leibniz" and they thought "Lebanese".
I think mst's using Arc's do, which is progn.
It is a classic C question not knowing about the sequence points and side-effects. It has nothing to do with either operator precedence or lexer behavior.
Of course. What I didn't mention is that my favourite language is C. :-)
:)
But in languages where + is a function there's a good chance you get 21.
gcc says 22 and it gives you a warning, that this expression is illegal, we looked it up, because you cannot use a variable which is ++incremented more than once in the same expression.
Compilers don't magically filter assignments out of expressions. The compiler already has the parse tree (+ x (1+ x)), and the arguments are pushed on the stack in reverse order because that's consistent with function calls (in c++ when you were to overload operator+ nothing would change, I suspect). So first 1+ x is evaluated and the value of x is updated, and the number 22 is returned.
Or to illustrate with a stack machine:
But the whole discussion is still silly, because the whole deal is undefined in any sane language (and for good reason). Unless variables become immutable you can't really prevent this kind of ambiguity from occurring, so it's no big deal.That's why you can infer that y = 21 in Java.
Would you call Java insane for that?
Edit: an explanation. GHC runs on graph reduction, and will do "normal order" reduction in the normal case. + is strict in both arguments, so (val x) will be fully evaluated before (inc x) is evaluated.
If we replace with a lazy operator like (:), then we can get different results. Here is a program which will evaluate the (inc x) first:
the expression is not fully evaluated until it is printed, and then it is evaluated in reverse order, so inc x runs before val x. The result is [11,11].Of course, none of this can be relied on. GHC does a lot of optimizations, and unsafe operations are unsafe.