views:

2592

answers:

15

I love recursion. I think it simplifies things a lot. Another may disagree; I think it also makes the code a lot easier to read. However, I've noticed that recursion is not used as much in languages such C# as they are in LISP (which by the way is my favorite language because of the recursion).

Does anybody know if there is any good reasons not use recursion in the languages such as C#? Is it more expensive than iteration?

+13  A: 

Are they more expensive than iterations?

Yes they are. Many Lisp variants support the idea of a "tail-call optimisation" which allows many uses of a recursive function call to be converted into an iterative one (this is simplifying a bit). If tail-call is not supported, then a recursive function call will use progressively more memory on the stack.

1800 INFORMATION
Many Lisps don't support tail calls.
Jules
@julesjacobs You're probably right, the one I wrote certainly didn't; however, it's good to note that Scheme *requires* it.
Aaron Maenpaa
Oh right, sorry I was thinking of Scheme
1800 INFORMATION
Any good compiler should optimize away tail calls. Pity that so many aren't good.
Greg
+9  A: 

Functional languages such as Lisp and F# can implement many tail recursive functions internally as loops and are able avoid the stack overhead of a function call. C# doesn't have support for tail recursion, although F# does.

Scott Weinstein
C# doesn't specify it, but the underlying CLR includes a tail call instruction, therefore it is a reasonable optimization. NB: as of .NET 2.0, tail call was SLOWER than a regular call.
plinth
+9  A: 

Are they more expensive than iterations?

Yes they are. Recursion requires creating a new stack frame along with a call and return whereas iteration generally only requires a compare and branch making it substantially faster; however, compilers can perform tail-call optimization on certain recursive calls (namely tail calls) which allow them to reuse the stack frame making the recursive call much less expensive and effectively turning them into iteration. Scheme actually requires that scheme compilers implement tail-call optimization.

Aaron Maenpaa
A: 

you should avoid recursion at all costs in any language! recursion causes unnecessary repeating computations and will slow your program to a crawl. Try generating factorials by recursion and you'll see what I mean. You should always try to cache results that will be used again instead of repeating the calculation. This is called memozing the function. This should always be preferred over recursion.

The cost and waste of repeating calculations is why recursion is a very bad idea!

klyde
-1, this is horrible advice. While there is almost always a better iterative way, sometimes recursion is the easiest to write and maintain with little to none performance hit. Recursion is one more tool on our belt and has its uses.
Samuel
Especially since some languages only give you recursion to perform repetition. Trying to avoid recursion in Scheme or XSLT would be silly and futile.
Aaron Maenpaa
hey, I said if possible! If must use recursion that's diffrerent, but if you have a choice you should always avoid it. I don't know of anyone would would disagree!
klyde
I could implement a tree transversing algorithm without using recursion, but that's a bad idea because the processor's stack operations are probably faster than using a queue myself! I think it's really situation dependent. Recursion is NOT a bad thing!
strager
oh yes recursion is BAD IF THERE IS A CHOICE, come on, I'm really disappointed with you guys.....let it go already and admit in any case WHERE THERE IS A CHOICE recursion IS VERY VERY BAD!!!!!
klyde
oh and by the way usually tree traversal MUST use recursion.....don't be sooooooo well ah hostile?
klyde
@strager:merci. I think any resursion can be converted to an iteration if you throw in a lot more thinking and caculations. Just don't know why many languages don't have build-in support for the convertions.
Tom
@klyde, No you don't have to use recursion. In ARM assembly, you could implement it by using push r15;b label instead of bl label. That's technically not recursion, but iteration. You can do similar things in C, re-implementing a stack. That's the point I was getting at -- There IS a choice!
strager
your being silly...grown ups understand that using recursion only when theres no CHOICE covers those situations.....wow, I guess I need to dumb down my answers
klyde
why don't you guys just give me - infinity, and use recursion to do the calculation
klyde
look not to seem well ah above it all but I been exposed to junior high algebra and yes recursion IN MATHEMATICS is beautiful and NECESSARY (especially if you want to PROVE stuff). However in computer science it is simply resource intensive and WASTEFUL so IF GIVEN A CHOICE AVOID IT LIKE THE PLAGUE
klyde
Klyde, the reason you're being voted down is that you're making unreasonable blanket statements that cover languages you're clearly not familiar with. Some computer languages are based on mathematics, and in those languages, recursion IS beautiful and necessary, not wasteful.
Joel Mueller
forget about the aesthetics, no matter which language your talking about recursion translates into infinite stack grown as well as unecessary duplication of calculations. I'm not arguing that recursion isn't beautiful, I'm simply saying that IF YOU HAVE A CHOICE caching results is preferale. Period
klyde
vote me down all you want it doesn't change the fact that to tell a beginning programmer not to memoize when possible is silly and detrimental to the apprentice! Oh come already, you cant possibly want to justify consuming resources so your code is beautiful now would you?
klyde
Why would you tell a beginning programmer to memoize? Why complicate things that much for him or her? And, yes, it is often worthwhile to use computer resources (normally cheap) to make it easier for the code to be read by humans (normally expensive).
David Thornley
hmmmmmm...cheap computing resources? that's why companies fight tooth over nail for every it dollar spent. I would submit memoization is actually less complicated than recursion. After all everyone knows what a cache is and why it's necessary
klyde
of course I meant IT dollar spent.
klyde
"no matter which language your talking about recursion translates into infinite stack grow[th]" http://www.letmegooglethatforyou.com/?q=tail+recursion
Joel Mueller
I see the Scheme is weak with this one. No, klyde, recursion does not necessarily "translate into infinite stack growth as well as unnecessary duplication of calculations."
Chuck
"By passing the data around as an extra parameter we remove the need to execute code after the recursive function call, so no stack space is required" - quoted from joel's call let me google it for youbut this smacks of caching to me!! and Eric -1 for attitude? please that's a bit one sided.
klyde
chuck - yeah, that's why SCHEME is nothing more than an an MIT TEACHING DEVICE.......try suggesting using scheme on a project someone is PAYING you do to. And yeah my SCHEME is weak since last time a used it was in uh 12th grade....
klyde
why is so offensive about admitting caching is better than unraveling a bloated stack??
klyde
The point, klyde, is that some languages have the ability to do an infinite amount of recursion without running out of stack space, and in some of those recursion is more common than iteration. "You should generally avoid recursion in most languages" would not have got a down vote.
Joel Mueller
A: 

I think recursive functions have to be put on a stack - each time the function calls itself, another copy of that function goes on a function stack, and so on. The problem is that, at some point, the stack runs out of space to store functions, so if the numbers get to big, a recursive solution may not work. I know because it bit me in the ass - I had a great recursive function to free() my entire linked list, and then I did a test of it with the biggest linked list I could make and got an error (I believe it was a segfault - definitely should have been a stack overflow :) ).

Iterative functions don't have these errors - in machine language, they are expressed as simple 'jmp's or 'je's or so on, so they never run out of room on the function stack and are, effectively, cleaner.

This is an entirely subjective question, but if it wasn't for the fact that recursion has a limit built-in to your computer, I would say it is a much better solution. Some iterative solutions to problems just look ugly, while the recursive solution looks so much cleaner and nicer. But such is life.

Chris Lutz
Functions are copied to the stack? I think you mean function /pointers/ are copied to the stack. Stack overflow is more common with managed code (Java, .NET) because the stack is no different from the heap (speaking generally) when it comes to unmanaged C/C++ (where read/write from unalloc'd memory
strager
causes a segmentation fault). Also, don't think all situations are simple for(x = 0; x < 42; ++x). Recursion usually isn't called for in those cases. I agree it is "subjective," but I think the choice between recursion and iteration is dependent on who's going to maintain the code.
strager
+6  A: 

Well besides everything else said here, the compiler and even more so the architecture of modern CPUs, can do lots of optimizations with iteration, that they can't do with recursion. One very important example is the ability of the processor to do optimistic computation. When the processor finds and iteration space, it knows how long it will take, from the beginning, there is no real need to check each time, before starting the next loop, so they pipeline the operations, and since most CPU can do several operations at the same time, through pipelining, you can solve the iteration space in less time than the recursion, even with tail-optimization, because the CPU is actually processing about 4 loops at a time, for a x4 performance gain, of course your mileage will very depending on the architecture of the CPU, but its likely to be a big part of it, with next gen CPUs pushing the gains even further than that.

The true problem with recursion is that our hardware is VonNeumann based (achievable variant of the Turing machine), and not Lisp machines, although there are a few specialized Lisp hardware, you won't find any desktop with it :)

Robert Gould
We need an award for the longest sentence ever posted on SO. ;)
Michael Myers
... longest ever *comprehensible* sentence, at least.
too much php
Comprehensible indeed, I didnt even notice the run-on until mmyers pointed it out, but I'm often guilty of that style, so I am immune to it. See?
Karl
I'm a literary freak apparently, totally unrolled that sentence there, wow.
Robert Gould
+3  A: 

There are many pros and cons to using recursion. Definitely the code simplicity is the biggest one which also lends itself to better code maintainability and less bugs.

The biggest danger to recursion are edge cases were the algorithm spins out of control to break the function stack limit. Some languages, Progress's ABL language for one, has a parameter for the highest level of nested calls allowed. These are usually low and adding recursion to the mix could make an application break that limit.

In short, recursion should always be implemented with tight termination cases otherwise it can be very difficult to debug (because of unpredictability) and can cause serious issues in production code.

For the concerns with memory and speed, unless this is a method itself is short (time wise) being called many times it really doesn't matter what the performance is.

Example: If you use recursion to scan all the files and folders of a hard drive the performance impact that the recursion does is minuscule to the time it takes to hit the hard drive and grab the file system information. In this case recursion is probably preferred over iterative processing.

Another example: If you scan the nodes of a tree structure, an iterative process maybe more beneficial because we are not involving the function stack as much which means we are hitting less memory and probably letting the hardware use more caching. See Robert Gould's response for more details.

Jeremy Edwards
A: 

When dealing with inherently linear data structure such as list or vector, one reason to prefer iterative construct over recursion is it conveys the intent of your code better. Oftentimes it requires more effort for the reader to discern the structure of your program when recursion is used indiscriminately when iteration suffices.

huaiyuan
+4  A: 

If an algorithm can be expressed most naturally in a recursive form, and if the stack depth is small (in the log(N) range, i.e. typically <20), then by any means use recursion. (Any performance gain due to iteration will be a small constant factor).

If there is any danger that the stack grows large, and if your language/compiler/runtime system doesn't guarantee the tail call optimization, you should avoid recursive algorithms.

mfx
A: 

If a problem can be reduced to an iteration, then I iterate.

If a problem calls for recursion (eg tree navigation) then I recurse.

That being said I primary make line of business apps in C# - I'm sure scientific programming has a different set of requirements.

JSmyth
A: 

The choice isn't based solely on the problem to be solved, but also on the language used. In C-style languages (Java, C#, or what have you) my knee-jerk response is to avoid recursion, as it looks completely alien to me (and I just can't think recursively), to say nothing of the potential for stack abuse. However, there are some problems for which it makes almost no sense to use anything other than recursion - tree traversal being a good example. An iterative solution is completely plausible, but the code would be bigger, buggier, and almost certainly less readable.

However, more dynamic language (such as Lisp or Python) go to great lengths to make recursion a more natural possibility. My personal response is to look for an iterative solution first, no matter what the problem, but varying mileage makes a horse race.

In the end, the best bet is probably to just write it. Chances are good that you'll throw it out once in any case.

Lee Crabtree
+1  A: 

Scheme is the only Lisp dialect I know of that requires tail-call optimization, and they tend to use recursion a lot. In other Lisp dialects that don't require this (like Common Lisp), I don't see recursion used any more than in any other language.

Ken
+2  A: 

Does anybody know if there is any good reasons not use recursion in the languages such as C#? Is it more expensive than iteration?

Yes, because C# doesn't support tail recursion. When using recursion for simple iteration through large collections, you can easily get a StackOverflowException and crash your application if you recurse too deeply.

munificent
A: 

I'll just throw out there that in XSLT variables are read-only once created. Because of this, things that would be done with indexed for loops, like

for(int i=0; i < 3; i++) doIt(i);

are actually done with recursion. Something equivalent to

public rediculous(i) {
    doIt(i);
    if (i < 3) rediculous(i + 1);
}

I would actually provide an XSLT example here, but all that typing makes Baby Jesus cry.

nsayer
Ridiculous surely?
Kev
Well, yeah, but XSLT sort of admits to no alternative. The code up there is pseudocode. With XSLT, of course, it would all be <xsl:template> nodes and stuff.
nsayer
It would be interesting with actual XSLT.
Peter Mortensen
A: 

Recursion is (impossible/much harder) to parallelize than iteration

Modern cpus have multi-cores therefore direct optimization with parallel.for (and such techniques) gets much harder if you designed for recursion.

However parallelization is still quite obscure and relatively few people uses it yet.

Furthermore, I think recursive algos are easier to design and think of because they involve slightly less code and variables at the same time. I usually go for recursion when there is no performance necessity.

Eric