if a > 0
then let a = a + 1
in # do smtg with a
else # do smtg with a
Of course the inner a within the let clause is a "different" a, because outside of the let clause the old a remains. This doesn't have to be slow either, because if the compiler detects that the outside a isn't used anymore, it can simply increment a memory location or a register.With a little bit of syntactic support from the language, you could easily write this in a natural, comfortable form, which will then automatically get compiled to the code above. In Haskell, it's pretty easy to do that with monads:
do $ when (a > 0)
a <- a + 1
(I haven't touched Haskell in a while so there might be some minor syntactic issue here, but the overall point still stands). The point here is that the number of potential branches can be determined at compile time, which makes the problem syntactic.A bigger problem is when you're dealing with iteration, and you can't know at compile time how long the loop is. Then you can't unroll it, which means the compiler implementors can't use the technique above. But they can use a different technique - recursion, which can later be compiled back to iteration via tail calls optimization, removing any awkwardness. Again, with the do monad, it's trivial in Haskell.
Of course the question is, if you go through all the trouble to build up the beautiful, elegant mechanics that make it possible to write imperative code that gets compiled to purely functional code, that gets compiled back into imperative machine code for efficiency - what's the point? IMO the point is mathematical beauty - something you can't easily put a price tag on. There are some empirical benefits as well, but I'm not sure if they outweigh the troubles. Anyway, there is a great argument here, but the author only scratches the surface of the problem and doesn't dig nearly deep enough to get to the meat of the problem.