[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: tail recursion proposal
I frequently run across Scheme refugees who are confused by an
expectation that all programming languages will support tail recursion
as Scheme does. Indeed, it's a common source of programming error for
Common Lisp users who used to be Scheme people and who are often
unable to express themselves iteratively using a "loop" notation, and
so end up blowing out of stack space. (Always ironic, to me, because
I thought the original point of the tail recursion exercise was to
give programmers flexibility about expression, not to trade one form
of dogma for another... I would feel more sympathetic toward them if
they knew what a loop was and were just grumbling about the expressive
inconvenience, but they often look at me with a stare like there is
something dirty or unhealthy or even just plain unknown about "loop"
constructs.) Anyway, I trace the cause of this inflexibility on their
part partly to the fact that I think S&ICP and its followers apparently
spend too little time on the "alternatives" part, but I trace THAT, in
turn, to this part of the Scheme spec which simply and without explanation
requires a certain behavior.
Now that we're going to spend time explaining things a little, I take
some specific issue with the following paragraph, which I consider
central to the issue. It appears to express a universal truth instead
of a design trade-off. And that, I think, is a shame.
| Proper tail-recursion is important because it allows iterative
| computations to be expressed efficiently, reliably, and portably
| using ordinary procedure calls.
I think the design trade-off is certainly one made by Scheme but it is
not the only legitimate such choice, and I would prefer to see wording
that did not fill the reader's head with Scheme-centric propaganda.
I also think the funny little list of adverbs here is odd in that they
really wants to be combining, not modifying expressed in a free-standing
way. There is nothing inherently "unreliable" or "unportable" about the
expression of a procedure in this way. What is unreliable or unportable
is only the space-efficiency. The minimal fix to this paragraph's complaint
is:
| Proper tail-recursion is important in Scheme because it allows
| iterative computations to be expressed using ordinary procedure
| calls with a space efficiency that is portably reliable.
But I would prefer more elaborated text, such as:
| The requirement to support proper tail recursion implicitly thwarts
| some techniques for ``stack debugging'', since if an error occurs,
| the chain of active continuations will have lost information about
| how the computation reached the present state. This was a
| consciously made design trade-off. Proper tail-recursion has
| traditionally been important in Scheme because it allows iterative
| computations to be expressed using ordinary procedure calls with a
| space efficiency that is portably reliable. Also, sufficient
| techniques are believed to exist so that it is usually possible for
| an implementation to compensate heuristically for the would-be loss
| of debugging power.