Note that there does not have to be a call from every function to every other function, for example, f can call g which calls h which calls f. You may hear people using the term strongly connected component (SCC). It’s not important for this article, but a SCC is a group of mutually recursive functions. Technically even a self-recursive function like map, or a non-recursive function is a SCC, the SCC just contains a single item. f is not a SCC on its own, it needs g and h.

In assembly and abstract machines procedure calls are handled by pushing a return address onto the stack and jumping to the callee. The call returns by popping the return address off the stack and jumping to it. Depending on the calling convention other information may also be placed on the stack. However the tail call, the last call of a procedure, doesn’t need to return to the caller, when it returns it can return to the caller’s caller, or if that’s a tail call the caller’s caller’s caller etc. It does this by not bothering to save the return address on the stack and simply jumping to the callee. When it’s time for the callee to return the desired return address will be in the correct place on the stack. In other words you can think of a tailcall as a goto. This is very easy for the compiler to do provided that it has low-level control over the generated code, it also works for recursive and non-recursive calls. Therefore we call it Last Call Optimisation.