qwertymk
qwertymk

Reputation: 35284

tail recursion and fibonacci

I was looking at this site: http://rosettacode.org/wiki/Fibonacci_sequence#JavaScript and saw this program:

function fib(n) {
  return function(n,a,b) {
    return n>0 ? arguments.callee(n-1,b,a+b) : a;
  }(n,0,1);
}

How does this work, what are those two arguments (a and b) help. I traced it and still can't figure out how this works

Upvotes: 7

Views: 5516

Answers (5)

I see a few problems that can lead to confusion. Short hand and tail optimization for recursive function pattern.

The problem might be in the short hand version of the code. Re-written for clarity below.

  1. acknowledging the anonymous function by giving it a name "recur"
  2. conditional (ternary) operator expanded.

Tail Optimization is used to tame the stack use of recursive functions by adding an accumulator part. This is a common pattern but takes away from the readability. That's the recur function.

A special note that performance is great compared to iterating in a loop.

function fib(n) {
    function recur(n, a, b) {
        if (n > 0) {
            return recur(n - 1, b, a + b);
        } else {
            return a;
        }
    }
    return recur(n, 0, 1);
}

With respect to the parameters, n is the iteration counter, a and b are the sequence parts of fibonacci.

Upvotes: 0

Justin Ethier
Justin Ethier

Reputation: 134187

a and b represent the current number of the sequence and the next number of the sequence, starting from 0 and 1. n is a count-down timer that specifies which element of the fibonacci sequence will be returned (EG: n = 10 will return 55).

This function works by accepting an argument n which means it will calculate nth number of the sequence:

function fib(n) {

The code then defines a function that will calculate the next number in the sequence:

function(n,a,b) {
  return n>0 ? arguments.callee(n-1,b,a+b) : a;
}

Basically this anonymous function counts down n by one each time it is executing, while at the same time moving a and b to the next numbers in the sequence. If n is equal to 0 then the sequence is complete and the current number a is returned.

arguments.callee refers to the currently executing function, so that code just means to call back into itself with the new arguments. In other words, to begin the next iteration of the "loop".

Finally, by saying (n,0,1); the code is actually calling into fib with the parameters n,0,1. The return statement - which I left out of the above snippet - takes the return value of the anonymous function and returns it to the caller of fib.


That said, using recursion in this manner is inefficient for languages such as JavaScript that do not have tail call optimization. For large n you would be better off writing this using a standard looping construct instead of recursion.

Upvotes: 1

hayesgm
hayesgm

Reputation: 9096

As explained here, arguments.callee refers to the current function you are in. Since the function you are in is anonymous, this is the only way to call the function and achieve recursion.

The specific function computes the Fibonacci sequence, by recursively calling in the inner function.

Upvotes: 1

zw324
zw324

Reputation: 27210

In the function(n,a,b), n serves as a countdown counter, and a b stores two consecutive Fibonacci numbers for the purpose of computing the next, so when n reaches 0, you have a as the n+1-th Fibonacci number (since the real Fibonacci has two 1s as the beginning).

E.g., n=4:

n  a  b
4  0  1
3  1  2
2  2  3
1  3  5
0  5  8

As you can see, the value of a and b always equal to the Fibonacci numbers. Also, this is very similar to Functional Programming (as the website stated Scheme programmers).

Upvotes: 9

nicholas.hauschild
nicholas.hauschild

Reputation: 42849

a and b are parameters into a newly defined anonymous function.

I would take a look at this page which is documentation about the arguments object. From the documentation, arguments.callee, is a reference to the function you are currently in. This has to be done because they are working in an anonymous function, so it really has no name (that they know of).

It seems as though they are recursively calling the function that they (anonymously) define to a depth of n. Along the way, they are calculating the fib numbers, and they return the value a once a depth of n has been met. The initial values passed into the function are (n,0,1)

Upvotes: 1

Related Questions