I don't see any variables in the tail recursion example, so maybe you're
confused by the term "variable" in this context. In an imperative
language, you can say:
i = 5; // assign the value 5 to i
i += 1; // now change the value from 5 to 6
What is the value of i in the above? It's 5 in one place and 6 in
another, i.e. it *varies*. That's why it's a *variable*. Functional
programming doesn't have variables. You can say
i = 5
which is called an "equation" rather than an assignment. It means i is
equal to 5, and anywhere you see "i" in that lexical scope, you can
substitute 5 instead ("referential transparency"). You can't change the
value of i once you have declared it to be 5. So you can't have a loop
like "for i = 1 to 5 do ..." since the value of i would change as you
went through the loop. Therefore, you use recursion like in the
stackoverflow thread, binding i to new values by creating new scopes
through the recursive calls. To print the numbers from 1 to 5 in
Haskell, you could say (untested):
f n = if n > 5
then return ()
else do { print n; f (n+1) }
main = f 1
You see there is a parameter called n, which doesn't vary, but instead,
we reach the next iteration by a new recursive call with the newly
computed parameter n+1. In practice in Haskell, you don't have to write
the recursions explicitly very often, since library functions (like map,
foldr, etc.) manage to hide most of it behind the scenes.
> Anyway, I'm still curious as to whether or not is tail recursion more
> expensive than traditional loops? :) Thanks for your input!!
Tail recursion and traditional loops should compile to the same code if
the compiler is careful.
You might read the book "Structure and Interpretation of Computer
Programs" (search for the title). The text is online if you don't
want a printed copy.