Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Tail recursive functions in Scheme

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

Question

I can do regular recursion fine, but I can't wrap my head around how to write the same thing using tail recursion.

Regular version:

    (define (factorial X)
      (cond
            ((eqv? X 1) 1)
            ((number? X)(* X (factorial (- X 1))))))
like image 228
Eogcloud Avatar asked Dec 01 '12 23:12

Eogcloud


1 Answers

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)))))
like image 173
Óscar López Avatar answered Oct 08 '22 21:10

Óscar López