Hacker News new | past | comments | ask | show | jobs | submit login

I might be confused, but do you mean "it doesn't do tail call optimization"? "Doing tail calls" is a bit of a strange phrase, if I understand the concept of what a tail call is—I'm under the impression that a tail call is just a call, that happens to be the final action in its scope. If a language can do "calls" at all then it can "do tail calls."



Yes, you're correct about the more general meaning. But in the Scheme world "doing tail calls" means something like being "properly tail recursive" (see https://www.gnu.org/software/guile/manual/html_node/Tail-Cal... for more details). It's not appropriate to call it an optimization because it's a foundational property of the language.


Got it. Thanks for giving more of the language-specific context on that.


It's best to call it "Tail Call Elimination". It's not a nice-to-have optimization in Scheme as using tail calls is the only way to iterate (do is a convenience built on tail calls), it's a necessity for any non-toy Scheme implementation.


Tail call elimination isn't a very good term.

- The only optimization that completely eliminates calls is inlining, so it is misleading. An optimized tail call still has some trappings of a call, like a control transfer somewhere else, with arguments.

- In Scheme lingo, the procedure calls so optimized are called tail calls; they are produced, and thus not eliminated. When the goto is taken, the procedure is said to be making a tail call, or tail calling. In assembly language, if you hand coded such a goto, you might put in a comment saying "this is a tail call", so it's not just Scheme lingo.


You know this, but being explicit helps the casual reader:

The "elimination" in "tail call elimination" refers to the "elimination" of the call frame.

In languages like C each call pushes a frame to the call stack. When the called procedure is done, execution returns to the site of the call. In a tail call there is no work to done, so the frame is now removed and execution continues where the previous frame points. But ... if we simply never omit the call frame, then executation then exectuation automatically returns to the parent frame.

The spec talks about allowing an "unbounded number of active tail calls". In an implementation with frames, it means tail calls can't just keep pushing frames.

Seen in isolation "tail call elimination" doesn't seem like a big deal, but combined with "real macros" (structural, scope-respecting macros) it is possible to implement control structures as a user without worrying about stack overflow.


In Scheme slang, a tail call is a procedure call that has been turned into a kind of goto, and so doesn't require a new stack frame or return linkage.

The term "tail call optimization" still makes sense, but refers to the production of tail calls out procedure calls that occur in the tail position, not to the reduction/elimination of tail calls.


Yes, this was an issue of me knowing general terminology (where this idea, or similar ones, show up in Haskell and Clojure, for example) but not the more specific parlance of Scheme. I'm happy to learn!




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: