For a function to be tail recursive, there must be nothing to do after the function returns except return its value. That is, the last thing that happens in the recursive step is the call to the function itself. This is generally achieved by using an accumulator parameter for keeping track of the answer:

(define (factorial x acc)
  (if (zero? x)
      acc
      (factorial (sub1 x) (* x acc))))

The above procedure will be initially called with 1 as accumulator, like this:

(factorial 10 1)
=> 3628800

Notice that the accumulated value gets returned when the base case is reached, and that the acc parameter gets updated at each point in the recursive call. I had to add one extra parameter to the procedure, but this can be avoided by defining an inner procedure or a named let, for example:

(define (factorial x)
  (let loop ((x x)
             (acc 1))
    (if (zero? x)
        acc
        (loop (sub1 x) (* x acc)))))
Answer from Óscar López on Stack Overflow
🌐
USNA
usna.edu › Users › cs › wcbrown › courses › F19SI413 › lec › l06 › lec.html
SI413: Scheme - list internals, tail-recursion, closures
Definition: A function is tail recursive if its output expression in every recursive case is only the recursive call. In Scheme, this means that the recursive call is outermost.
🌐
Scheme
docs.scheme.org › schintro › schintro_73.html
An Introduction to Scheme and its Implementation - Tail Recursion
Some compilers for languages such as Common Lisp and C perform a limited form of "tail call optimization," but Scheme's treatment of tail calls, is more general, and standardized, so you can use recursion more freely in your programs, without fear of stack overflow if you code your routines tail-recursively.
Discussions

recursion - Tail recursive functions in Scheme - Stack Overflow
I'm studying for a Christmas test and doing some sample exam questions, I've come across this one that has me a bit stumped I can do regular recursion fine, but I can't wrap my head around how to w... More on stackoverflow.com
🌐 stackoverflow.com
A function which checks if a function in tail-recursive?
Recall that a function call is said to be tail recursive if there is nothing to do after the function returns except return its value. Assume that we have a function that does this, let's call it tail-recursive?. Now, consider the following function: (define self-tail-recursive? (lambda () (if (tail-recursive? self-tail-recursive?) #t (self-tail-recursive?)))) Ask yourself -- is self-tail-recursive? tail-recursive? More Formally Assume that we have a function tail-recursive? that decides for all functions whether or not they are indeed tail recursive. Now, define the function halts? as: (define halts? (lambda (f) (tail-recursive? ((lambda (k) (lambda () (begin (f) (k k)))) (lambda (k) (k k)))))) So, we have a functioning solution to the halting problem =><=. This is a contradiction -- hence our assumption that we have a functional tail-recursive? function is false. EDIT: This only shows you can't have a function that determines if a function will Tail-call itself. You could have one that says a function can tail-call itself. You could accomplish this by walking the AST and asserting that the tail-call is in the last possible position. More on reddit.com
🌐 r/scheme
5
4
October 26, 2016
recursion - scheme - Is function tail-recursive? - Stack Overflow
I have implemented this recursive function in scheme: (define f (lambda (n) (cond ((= n 0) 0) ((= n 1) 2) ((= n 2) 37) ((odd? n) (+ (f (- ... More on stackoverflow.com
🌐 stackoverflow.com
What is tail recursion?
Haskell: Naturally supports tail recursion due to its functional nature. Scheme: Tail recursion is a standard feature. More on designgurus.io
🌐 designgurus.io
1
10
August 1, 2024
🌐
University of Texas
cs.utexas.edu › ftp › garbage › cs345 › schintro-v14 › schintro_127.html
An Introduction to Scheme and its Implementation - Recursion in Scheme
The recursive calls to eval are tail calls, and since it's implemented in Scheme, the interpreter relies on the underlying Scheme's tail-call optimization. The evaluator thus snarfs the tail-call optimization from the underlying Scheme system.
🌐
MIT CSAIL
people.csail.mit.edu › jaffer › r5rs › Proper-tail-recursion.html
Proper tail recursion - Revised(5) Scheme
Implementations of Scheme are required to be properly tail-recursive. Procedure calls that occur in certain syntactic contexts defined below are `tail calls'. A Scheme implementation is properly tail-recursive if it supports an unbounded number of active tail calls.
🌐
Owlnet
owlnet.rice.edu › ~comp210 › 96spring › Labs › lab09.html
Lab 9 Tail recursion and loops
For a tail call, Scheme doesn't have to remember anything, because there is nothing more to do: after it is done with the current function call, it is really done.
🌐
MIT CSAIL
groups.csail.mit.edu › mac › ftpdir › scheme-reports › r5rs-html.old › r5rs_22.html
Revised(5) Report on the Algorithmic Language Scheme - Tail recursion
Implementations of Scheme are required to be properly tail-recursive. Procedure calls that occur in certain syntactic contexts defined below are `tail calls'. A Scheme implementation is properly tail-recursive if it supports an unbounded number of active tail calls.
Find elsewhere
🌐
Wikipedia
en.wikipedia.org › wiki › Tail_call
Tail call - Wikipedia
4 weeks ago - The Scheme language definition formalizes the intuitive notion of tail position exactly, by specifying which syntactic forms allow having results in tail context. Implementations allowing an unlimited number of tail calls to be active at the same moment, thanks to tail-call elimination, can also be called "properly tail recursive...
🌐
GNU
gnu.org › software › guile › manual › html_node › Tail-Calls.html
Tail Calls (Guile Reference Manual)
Scheme is “properly tail recursive”, meaning that tail calls or recursions from certain contexts do not consume stack space or other resources and can therefore be used on arbitrarily large data or for an arbitrarily long calculation.
🌐
Reddit
reddit.com › r/scheme › a function which checks if a function in tail-recursive?
A function which checks if a function in tail-recursive? : r/scheme
October 26, 2016 - So, we have a functioning solution ... tail-recursive? function is false. ... This only shows you can't have a function that determines if a function will Tail-call itself. You could have one that says a function can tail-call itself. You could accomplish this by walking the AST and asserting that the tail-call is in the last possible position. ... In this context of a scheme sub-reddit, ...
🌐
University of Washington
courses.cs.washington.edu › courses › cse341 › 08au › scheme › recursion.html
CSE 341 -- Recursion and Applicative Programming
;; example: member: (define (my-member e x) (cond ((null? x) #f) ((equal? e (car x)) #t) (else (my-member e (cdr x))))) A less commonly seen form is single-test tail recursion. Scheme compilers handle tail recursion very efficiently, as efficiently as a program that just uses loops instead of recursion.
🌐
Southwestern University
people.southwestern.edu › ~owensb › PL › RecursionLambdaLab.htm
Scheme Recursion/Lambda Lab
Recursion is a term used to describe a procedure that calls itself, directly or indirectly. In Scheme, simple program repetition/iteration can be achieved via recursion by having a function call itself. Most programs are tail recursive, where the recursive call is the last action that occurs.
🌐
Albertwu
albertwu.org › cs61a › review › tail › basic.html
Tail Recursion: basic-level questions - Albert Wu
A tail context is a location in a Scheme function that the interpreter can identify as tail recursive. A Scheme function needs to be written in a particular way in order for the interpreter to realize that it should perform tail call optimization.
🌐
ScienceDirect
sciencedirect.com › topics › computer-science › tail-recursion
Tail-Recursion - an overview | ScienceDirect Topics
Recall that Scheme, like all Lisp dialects, uses Cambridge Polish notation for expressions. The lambda keyword is used to introduce a function. As recursive calls return, our code calculates the sum from “right to left”: from high down to low. If the programmer (or compiler) recognizes that addition is associative, we can rewrite the code in a tail-recursive form:
Top answer
1 of 3
4

In your first code block, f is not tail recursive. The recursive call to f has to happen, return its result, and then 1 or 7, depending on the branch, has to be added to the result. Since the call to recursive call to f has to return, and there are arbitrarily many recursive calls to f, this means that arbitrarily many stack frames must be allocated.

When you think of calling a function, it may help to imagine that you take a new piece of paper and write all the of the local variables and values on that piece of paper. When you're determining the result of the function, there may be recursive calls to the same function. If the call is a tail-call, then when you take a piece of paper for it, you can throw away the old sheet, since you don't need any of its values anymore.

For instance, consider two ways of computing the length of a list:

(define (length-1 list)
  (if (null? list)
      0
      (+ 1
         (length-1 (cdr list))))) ; recursive call, NOT a tail-call

In this implementation, you have to finish the recursive call to length-1, get its result, and add 1 to it. That means that you need somewhere to come back to after the recursive call. Now consider a tail-recursive version:

(define (length-2 list current-length)
  (if (null? list)
      current-length
      (length-2 (cdr list) ; recursive call, IS a tail-call
                (+ 1 current-length))))

In this version, once you start to make the recursive call to length-2, you don't need any context from the original call anymore. In fact, you could translate this to a loop by assigning (cdr list) to list, and assigning (+ 1 current-length) to current-length. You can reuse the same stack space. That's how tail call optimization (when the tail call is to the same function) is equivalent to a loop.

2 of 3
0

The tail recursive function will pass the accumulated result into each call, so that once the end condition is reached, the result can be immediately returned by that last call of the function.

A non-tail recursive function will require something be done to the result after it has been returned. So, each layer of recursion has to be remembered so that it can work its way back out to calculate the final result.

In your first example, you are adding to the result of the next call of f, so it is not tail recursive.

The second example is also adding to the next call of loop, so it is not tail recursive.

The third example, passes the final result in as an argument into the next function call, so it is tail recursive.

🌐
Tufts University
cs.tufts.edu › ~nr › cs257 › archive › will-clinger › proper-tail-space.pdf pdf
Proper Tail Recursion and Space Efficiency William D Clinger Northeastern
Proper Tail Recursion and Space Efficiency · William · D Clinger · Northeastern · University · will@ccs.neu.edu · Abstract · The IEEE/ANSI · standard for Scheme requires implementa- tions to be properly tail recursive. This ensures that portable · code can rely upon the space efficiency ...
🌐
Fhdkmrn
fhdkmrn.github.io › resources › cs61a › scheme.html
Scheme and Tail Recursion Practice Problems
1. Implement remove, which takes in a scheme list and outputs a new one without any instances of the passed in element. (define (remove lst elm)) (cond ((null? item) nil) ((= (car lst) item) (remove (cdr lst) item)) (else (cons (car lst) (remove (cdr lst) item))))) (define (remove lst elm)) "YOUR CODE HERE" Toggle Solution · 2. Implement the above function, remove, tail recurisvely.
Top answer
1 of 1
10
What is Tail Recursion? Tail recursion is a special case of recursion where the recursive call is the last operation in the function. In tail-recursive functions, the result of the recursive call is immediately returned as the result of the current function call, without any additional computation. This allows for optimizations that can make tail-recursive functions more memory efficient than non-tail-recursive functions. Characteristics of Tail Recursion Last Operation: The recursive call is the final action in the function. No Pending Operations: After the recursive call returns, there are no further computations to be performed. Optimization Potential: Tail-recursive functions can be optimized by reusing the current function's stack frame, making the recursion as efficient as iteration. Tail Recursion Example Consider the calculation of the factorial of a number using tail recursion: Non-Tail-Recursive Factorial In a non-tail-recursive implementation, the multiplication happens after the recursive call returns: def factorial(n): if n == 0: return 1 else: return n * factorial(n - 1) print(factorial(5)) # Output: 120 Tail-Recursive Factorial In a tail-recursive implementation, the recursive call is the last operation: def factorial_tail(n, acc=1): if n == 0: return acc else: return factorial_tail(n - 1, n * acc) print(factorial_tail(5)) # Output: 120 Benefits of Tail Recursion Memory Efficiency: Tail-recursive functions can be optimized by reusing the current stack frame, preventing stack overflow for deep recursion. Performance: Reduces the overhead associated with recursive calls.
🌐
UMBC
courses.cs.umbc.edu › 331 › fall11 › notes › scheme › tailRecursion.pdf pdf
Tail Recursion
Scheme’s top level loop 3 · • There might be more than one tail recursive call · (define (repl1 n) (prinM “~s> “ n) (print (eval (read))) (if (= n 9) (repl1 0) (repl1 (add1 n)))) • What’s important is that there’s nothing more · to do in the func3on aWer the recursive calls ·