views:

247

answers:

9

I am currently working in PHP, so this example will be in PHP, but the question applies to multiple languages.

I am working on this project with a fiend of mine, and as always we were held up by a big problem. Now we both went home, couldn't solve the problem. That night we both found the solution, only I used a loop to tackle the problem, and he used recursion.

Now I wanted to tell him the difference between the loop and recursion, but I couldn't come up with a solution where you need recursion over a normal loop.

I am going to make a simplified version of both, I hope someone can explain how one is different from the other.

Please forgive me for any coding errors

The loop:

printnumbers(1,10);

public function printnumbers($start,$stop)
{
    for($i=$start;$i<=$stop;$i++)
    {
        echo $i;
    }
}

Now the code above just simply prints out the numbers.

Now let's do this with recursion:

printnumbers(1,10);

public function printnumbers($start,$stop)
{
    $i = $start;
    if($i <= $stop)
    {
        echo $i;
        printnumbers($start+1,$stop);
    }
}

This method above will do the exact same thing as the loop, but then only with recursion.

Can anyone explain to me what there is different about using one of these methods.

A: 

Compared to loops, a function call has its own overhead like allocating stack etc. And in most cases, loops are more understandable than their recursive counterparts.

Also, you will end up using more memory and can even run out of stack space if the difference between start and stop is high and there are too many instances of this code running simultaneously (which can happen as you get more traffic).

Amarghosh
+1  A: 

Well, I don't know about PHP but most languages generate a function call (at the machine level) for every recursion. So they have the potential to use a lot of stack space, unless the compiler produces tail-call optimizations (if your code allows it). Loops are more 'efficient' in that sense because they don't grow the stack. Recursion has the advantage of being able to express some tasks more naturally though.

In this specific case, from a conceptual (rather than implementative) point of view, the two solutions are totally equivalent.

Mau
+6  A: 

Loops and recursions are in many ways equivalent. There are no programs the need one or the other, in principle you can always translate from loops to recursion or vice versa.

Recursions is more powerful in the sense that to translating recursion to a loop might need a stack that you have to manipulate yourself. (Try traversing a binary tree using a loop and you will feel the pain.)

On the other hand, many languages (and implementations), e.g., Java, don't implement tail recursion properly. Tail recursion is when the last thing you do in a function is to call yourself (like in your example). This kind of recursion does not have to consume any stack, but in many languages they do, which means you can't always use recursion.

augustss
The problem in those languages that does not support tail recursion, is that the stack is often fairly small - causing stackoverflow on large structures. In languages Java or C# you should use a explicit stack instead of recursion (on large or unknown structures).
Moberg
I never thought the difference between these two were so minimal. There are only some language functionality issues, and performance issues. I thought there would be lots of practical differences, guess I was wrong.
Saif Bechan
+2  A: 

In general, a recursive function will consume more stack space (since it's really a large set of function calls), while an iterative solution won't. This also means that an iterative solution, in general, will be faster because.

I am not sure if this applies to an interpreted language like PHP though, it is possible that the interpreter can handle this better.

Christoffer
+1  A: 

A loop will be faster because there's always overhead in executing an extra function call.

A problem with learning about recursion is a lot of the examples given (say, factorials) are bad examples of using recursion.

Where possible, stick with a loop unless you need to do something different. A good example of using recursion is looping over each node in a Tree with multiple levels of child nodes.

Evan Trimboli
+1 for:"Where possible, stick with a loop unless you need to do something different". I never truly understood the full purpose of recursion, that why I never knew if the solution would be better using recursion. Now I know that recursion is a solution to a problem where a loop does not suffice.
Saif Bechan
@SaifBechan: I disagree with eh dogma of staying with loops; recursion often reflects the problem better than loops, trying to force fit a recursive problem into iteration often leads to complex and hard to understand code (and vice versa).
Lie Ryan
Nobody said anything about dogma. In a majority of cases, you probably don't need recursion.
Evan Trimboli
Recursion adds complexity where it's rarely needed. If you're working with a tree, sure. Recursion is a natural fit. But in most other cases, a loop will do the job and be more understandable at the same time.
cHao
+2  A: 

Recursion is a bit slower (because function calls are slower than setting a variable), and uses more space on most languages' call stacks. If you tried to printnumbers(1, 1000000000), the recursive version would likely throw a PHP fatal error or even a 500 error.

There are some cases where recursion makes sense, like doing something to every part of a tree (getting all files in a directory and its subdirectories, or maybe messing with an XML document), but it has its price -- in speed, stack footprint, and the time spent to make sure it doesn't get stuck calling itself over and over til it crashes. If a loop makes more sense, it's definitely the way to go.

cHao
Recursion is not always slower. The speed depends on language implementation in use.
oherrala
The only time it's not slower is when the language/compiler can do tail call optimization. Even then, i've never seen it be faster. A function call involves storing params (or pointers to params), pushing the return address, and jumping to the function. That's in *any* language that supports functions, because that's pretty much what a function is -- a list of instructions with a defined entry point, (optionally) a way to take params (which, in languages that support recursion, pretty much requires a stack), and a way to get back. In comparison, a loop does a store and a jump.
cHao
Tail call optimization is just a jump in disguise. And the only way recursion even *could* be faster than looping is if your language hobbles looping -- in which case, i won't be using it anyway.
cHao
+5  A: 

Often, a problem is easier expressed using recursion. This is especially true when you talk about tree-like data structures (e.g. directories, decision trees...).

These data structures are finite in nature, so most of the time processing them is clearer with recursion.

When stack-depth is often limited, and every function call requires a piece of stack, and when talking about a possibly infinite data structure you will have to abandon recursion and translate it into iteration.

Especially functional languages are good at handling 'infinite' recursion. Imperative languages are focused on iteration-like loops.

xtofl
+1 Thank you for static a practical difference, the tree like structures. I can imagine how recursion would be ideal for this situation, as you can easily skip to another point in the tree.
Saif Bechan
A: 

You don't really need recursion for a flat structure like that. The first code I ever used recursion in involved managing physical containers. Each container might contain stuff (a list of them, each with weights) and/or more containers, which have a weight. I needed the total weight of a container and all it held. (I was using it to predict the weight of large backpacks full of camping equipment without packing and weighing them.) This was easy to do with recursion and would have been a lot harder with loops. But many kinds of problems that naturally suit themselves to one approach can also be tackled with the other.

Kate Gregory
A: 

Stack overflow.

And no, I don't mean a website or something. I MEAN a "stack overflow".

Turing Complete