A function can be tail-call optimized if it returns a straight call to itself or no call to itself. The function mylength-inner will return either x
or (mylength-inner (cdr s) (+ x 1))
, and so it can be tail-optimized.
This means the compiler can turn it into a loop instead of calling the function recursively. Either return x, or assign (cdr s) to s, increment x, and start again at the top. (The Scheme standard requires that implementations be able to do this optimization, while the Common Lisp standard leaves it up to the implementation. Of course, this optimization is a very useful thing, so most implementations will do it.)
In the non-optimized version, l doesn't just return a call to l, but rather the result of a call to l with one added. This means it can't be directly turned into a loop, so all the function calls will have to be made.
Suppose the compiler wanted to turn l into a loop. There's no problem with the assignment of (rest s) to s, but where does it put the (1 + ...)
?