dtech
dtech

Reputation: 49329

Tail call optimization besides tail recursion?

Are there any tail call optimizations possible besides tail recursion? I've been trying to find or think of one that doesn't involve recursion, but with no success. Is it possible? Any examples?

Upvotes: 5

Views: 507

Answers (2)

user395760
user395760

Reputation:

Sure, "tail call optimization" is in fact the term for this kind of optimization in its most general, recursion-agnostic form. This optimization doesn't replace recursion with the equivalent of a while loop or something like that. Instead, tail calls are transformed such that the caller's stack frame is re-used. Any code of the form return f(...) or f(...); return is amendable to this. It works for any f, even for function pointers/closures/virtual methods where the compiler can't possibly know what is being called. Therefore it also works better with separate compilation, higher-order functions, late binding, etc.

If you look at enough code, be it functional or imperative, you'll find occasional calls which aren't followed by anything. A common case is when the caller delegates to the callee for the main task and only does some additional preparations. In functional code, you'll often find many small functions which do only one thing and are implemented in terms of other small functions, so you wind up with several layers of applying a simple transformation to the arguments, then performing a tail call to the next layer (with the transformed data as argument). TCO optimizes the second step, it (ideally) makes the call as cheap as a simple jump and makes the nice, modular code take as little stack space than a more monolithic implementation. In an object oriented design you may want to compose an object of other objects and expose convenience methods that delegate:

SomeClass doSomething(Argument a) {
    log.debug("Doing something");
    return this.somethingDoer.doIt(a, this.someExtraData);
}

Another example that's technically mutually recursive, but usually only has very few activations of any given function (with dozens or hundreds of other activations in between), are state machines implemented by having a function per state and calling it to enter that state:

void stateA() {
    // do actual work
    // determine which transition applies
    stateB();
}

void stateB() {
    // do actual work
    // determine which transition applies
    state...();
}

// dozens, possibly hundreds of other states

Upvotes: 3

user541686
user541686

Reputation: 210765

int bar(int x);
int foo(int x) { return bar(x); }

foo can simply jump to bar who returns to the caller directly; no recursion is necessary anywhere.

Upvotes: 1

Related Questions