Questions tagged [tail-call]

Tail call is a subroutine call that happens inside another procedure as its final action; it may produce a return value which is then immediately returned by the calling procedure.

The call site is then said to be in tail position, i.e. at the end of the calling procedure. If any call that a subroutine performs, such that it might eventually lead to this same subroutine being called again down the call chain, is in tail position, such a subroutine is said to be tail-recursive, which is a special case of recursion. Tail calls need not be recursive – the call can be to another function – but tail recursion is particularly useful, and often easier to handle in implementations.

Tail calls are significant because they can be implemented without adding a new stack frame to the call stack. Most of the frame of the current procedure is not needed any more, and it can be replaced by the frame of the tail call, modified as appropriate (similar to overlay for processes, but for function calls). The program can then jump to the called subroutine. Producing such code instead of a standard call sequence is called tail call elimination, or tail call optimization. Tail call elimination allows procedure calls in tail position to be implemented as efficiently as goto statements, thus allowing efficient structured programming. In the words of Guy L. Steele "in general procedure calls may be usefully thought of as GOTO statements which also pass parameters, and can be uniformly coded as [machine code] JUMP instructions" – see history for further discussion.

Traditionally, tail call elimination is optional. However, in functional programming languages, tail call elimination is often guaranteed by the language standard, and this guarantee allows using recursion, in particular tail recursion, in place of loops. In such cases, it is not correct (though it may be customary) to refer to it as an optimization. The special case of tail recursive calls, when a function calls itself, may be more amenable to call elimination than general tail calls, when the function may be different.

30 questions
14
votes
4 answers

How to recognize what is, and what is not tail recursion?

Sometimes it's simple enough (if the self call is the last statement, it's tail recursion), but there are still cases that confuse me. A professor told me that "if there's no instruction to execute after the self-call, it's tail recursion". How…
fingerprint211b
  • 1,176
  • 12
  • 24
6
votes
2 answers

Immutable Trie structure in F#

I am playing around with the aho-corasick algorithm to try and get a little better with F#, and I ran across a problem with the Trie implementations, they are all mutable or can't be tail call optimized. The basic issue from what I can see is that…
Snark
  • 1,664
  • 14
  • 27
5
votes
1 answer

how is C# tail recursion optimization possible when a stack trace is returned when an exception is raised

I'be seen a few questions regarding missing tail call optimization in C# supposedly making the language ill suited for recursive algorithm implementations. this, however,begs the question, how can we do tail call optimizations and still provide…
Carlo V. Dango
  • 13,322
  • 16
  • 71
  • 114
5
votes
5 answers

Functional languages with concurrent garbage collectors?

Microsoft's new F# programming language provides the powerful combination of functional programming (first-class lexical closures and tail calls) with an efficient concurrent garbage collector that makes it easy to leverage multicores. OCaml,…
J D
  • 48,105
  • 13
  • 171
  • 274
5
votes
2 answers

Does Arduino support tail call elimination?

I was wondering if the standard Arduino environment support tail call elimination... Does anyone know something about it?
4
votes
2 answers

How do I refactor a recursion occurring in a for loop to make it a tail call?

Consider the recursive subroutine append_until_exhausted. The recursion occurs in the middle of the body. I want to place it at the end for further processing, that is to say a simple tail call (without any optimisation, which in Perl typically…
daxim
  • 39,270
  • 4
  • 65
  • 132
3
votes
2 answers

CIL (MSIL) tailcall recursion in instance methods

Background: I am programming a .NET compiler (very similar to C#) for a school project. One of the features I am currently trying to add is tailcall recursion within methods. More info: In CIL, the "this" is passed into instance methods as if it…
leviathanbadger
  • 1,682
  • 15
  • 23
3
votes
2 answers

Do bound functions support proper tail calls in ES6?

In the ECMAScript 2015 Language Specification, the definitions of Function.prototype.apply and Function.prototype.call both include "Perform PrepareForTailCall()" as one of their steps, so we know that these functions support proper tail calls…
cpcallen
  • 1,834
  • 1
  • 16
  • 27
3
votes
1 answer

Tail recursion [C]

The question in my book is "Which of the recursive calls (not functions!) are tail recursive?" unsigned f(unsigned x) { if(x==0) return 1; else if(x==1) return f(x-1); else return 3*x + f(x-1); } In this example, I'm guessing that…
3
votes
3 answers

Visual C++ Tail Call Optimization

According to answers to that question: Which, if any, C++ compilers do tail-recursion optimization? it seems, that compiler should do tail-recursion optimization. But I've tried proposed options and it seems that compiler can't do this optimization…
2
votes
2 answers

Tail recursive remove duplicate consecutive entries in list

I'm attempting problem 8 of the 99 OCaml problems, which asks you to write a function compress that removes consecutive duplicate entires in a list: assert ( compress [ "a"; "a"; "a"; "a"; "b"; "c"; "c"; "a"; "a"; "d"; "e"; "e"; "e"; "e" ] =…
Jay Mody
  • 3,727
  • 1
  • 11
  • 27
2
votes
1 answer

Is it possible to make a proper tail-call of hanoi tower in lua?

I made a code of tower of hanoi problem with recursion and run it on the online lua compiler. If I put the input over 14, it didn't run. local num = io.read("*n") local count = 0 function hanoi(n, st, mid, dst) if n == 1 then count =…
jiny
  • 57
  • 3
2
votes
2 answers

Erlang, Last Call Optimization, lambda functions, and how to prevent growing a stack

I'm writing some Erlang code, and I've run into a bizarre situation that I don't understand. The code: -module(recursive_test). -export([a/2]). a(_, []) -> ok; a(Args, [H|T]) -> F = fun() -> a(Args, T) end, io:fwrite( "~nH:…
2
votes
1 answer

Why does my tail calling function not pause and flush output?

I have looked through lua-users Sleep Function reference in an effort to find a non-busy waiting solution to the sleep problem and I'm not happy with any of them. Nonetheless I attempted using several to provide a delay at the end of a function…
Stephen
  • 1,607
  • 2
  • 18
  • 40
2
votes
2 answers

When executed will this be a tail call?

Once compiled and ran will this behave as a tail call? let rec f accu = function | [] -> accu | h::t -> (h + accu) |> f <| t Maybe there is an easy way to test behavior that I'm not aware of, but that might be another question.
Iter
  • 361
  • 2
  • 10
1
2