Live data from Hacker News

Ask HN: What would Your_Favorite_Compiler do?

news.ycombinator.com

21–28 of 28 posts

Re: Ask HN: What would Your_Favorite_Compiler do?

#21

    val x = unsafePerformIO $ readIORef x

    inc x = unsafePerformIO $ modifyIORef x (1+) >> readIORef x

    main = do
      x 
The result is 21.

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:

    main = do
      x 
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.

Re: Ask HN: What would Your_Favorite_Compiler do?

#22
post #2

(let* ((x 10) (y x)) (+ x (incf x))) vs (let* ((x 10) (y x)) (prog1 (+ x x) (incf x))) [INCF does it with side-effects, use 1+ or directly evaluate (+ 1 x) for the clean version] Not everyone puts up with semantic ambiguity in operator precedence and evaluation. Some of us program in parse trees, directly :-)

Not really. ++x (as opposed to x++) is expected to return the incremented value, not the pre-increment value. So your choices are

  (+ x (incf x))
and

  (do
    (incf x)
    (+ x x))
depending on whether the language evaluates arguments in order, or if it builds the arguments as cells to observe and then reads their values (there's presumably a technical term for that which I can't remember - I blame sunday :)

So 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.

Re: Ask HN: What would Your_Favorite_Compiler do?

#24
post #22
post #2

(let* ((x 10) (y x)) (+ x (incf x))) vs (let* ((x 10) (y x)) (prog1 (+ x x) (incf x))) [INCF does it with side-effects, use 1+ or directly evaluate (+ 1 x) for the clean version] Not everyone puts up with semantic ambiguity in operator precedence and evaluation. Some of us program in parse trees, directly :-)

Not really. ++x (as opposed to x++) is expected to return the incremented value, not the pre-increment value. So your choices are (+ x (incf x)) and (do (incf x) (+ x x)) depending on whether the language evaluates arguments in order, or if it builds the arguments as cells to observe and then reads their values (there's presumably a technical term for that which I can't remember - I blame sunday :) So in C it's undef…

What do you mean by "not really"? :-P

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:

  f(x) -> x + succ(x)
  y = f(10) 
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".

Re: Ask HN: What would Your_Favorite_Compiler do?

#25
post #24
post #22

Earlier quoted context omitted.

Not really. ++x (as opposed to x++) is expected to return the incremented value, not the pre-increment value. So your choices are (+ x (incf x)) and (do (incf x) (+ x x)) depending on whether the language evaluates arguments in order, or if it builds the arguments as cells to observe and then reads their values (there's presumably a technical term for that which I can't remember - I blame sunday :) So in C it's undef…

What do you mean by "not really"? :-P 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. Alge…

>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.

I think mst's using Arc's do, which is progn.

Re: Ask HN: What would Your_Favorite_Compiler do?

#26
post #24
post #22

Earlier quoted context omitted.

Not really. ++x (as opposed to x++) is expected to return the incremented value, not the pre-increment value. So your choices are (+ x (incf x)) and (do (incf x) (+ x x)) depending on whether the language evaluates arguments in order, or if it builds the arguments as cells to observe and then reads their values (there's presumably a technical term for that which I can't remember - I blame sunday :) So in C it's undef…

What do you mean by "not really"? :-P 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. Alge…

> The poster's question is a classic comp.lang.c "favorite"; misunderstanding operator precedence and the two flavors of incrementing in C.

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.

Re: Ask HN: What would Your_Favorite_Compiler do?

#27
post #19
post #4

My_Favourite_Compiler would compile "x + ++x" as a call to abort(3). I think "undefined behaviour" is a horrible idea.

Undefined depends on the language. In many languages, the precedence rules are explicit enough that this code is clearly defined. In Ultilang (my own), Boo, and others, this would be parsed as x + {x += 1; x} and processed left-to-right.

Undefined depends on the language.

Of course. What I didn't mention is that my favourite language is C. :-)

Post reply on HN