Iteration is more performant than recursion, right? Then why do some people opine that recursion is better (more elegant, in their words) than iteration? I really don't see why some languages like Haskell do not allow iteration and encourage recursion? Isn't that absurd to encourage something that has bad performance (and that too when more performant option i.e. recursion is available) ? Please shed some light on this. Thanks.

- 510,854
- 105
- 1,084
- 1,005

- 1
- 1
- 3
- 6
-
6"Isn't that absurd to encourage something that has bad performance" If you think recursion in functional programming 'has bad performance' you don't understand functional programming. Features like memoization make recursion perform completely unlike it does in a language like C. – Frank Farmer Feb 02 '10 at 16:17
-
Related: http://stackoverflow.com/questions/72209/recursion-or-iteration – Jørn Schou-Rode Feb 02 '10 at 16:25
-
4Recursion imposes a higher cognitive load on the developer than does iterative loops. Recursion is great for directory scanning, but its greatest draw back is that it is memory limited - Stack Overflow! – logout Feb 02 '10 at 16:27
-
I think this question, by mentioning Haskell, is distinct enough from 72209 to be considered a independent question, with some editing. The answers for these two questions are covering different ground. – James McMahon Feb 02 '10 at 16:28
-
16"so-called sophisticated languages like Haskell" - Blasphemy! Burn him at stakes! x-( – missingfaktor Feb 02 '10 at 16:39
-
1@Rahul: Burning at the stake is not quite warranted. Voting to close the question as "subjective and argumentative" is. – David Thornley Feb 02 '10 at 17:56
-
8"To iterate is human, to recurse divine." Recursive solutions to problems tend to reveal the structure of the problem itself, thus making it easier to later formulate higher-order abstractions. Iteration tends not to do that. That's one reason to recurse instead of iterate. – afkbowflexin Sep 22 '10 at 17:55
-
1Sometimes iteration is more readable. line m = iterate (+ m) ...vs... line m y = y : line m (y + m). Normally we think of recursion as an abstraction on iteration but the reverse is also true. – Samuel Danielson Nov 28 '10 at 22:32
18 Answers
Iteration is more performant than recursion, right?
Not necessarily. This conception comes from many C-like languages, where calling a function, recursive or not, had a large overhead and created a new stackframe for every call.
For many languages this is not the case, and recursion is equally or more performant than an iterative version. These days, even some C compilers rewrite some recursive constructs to an iterative version, or reuse the stack frame for a tail recursive call.
-
2
-
16On real machines, iteration is better. Some languages have you write for real machines, and some languages have you write for imaginary machines where that's not true, and then translate your code for the benefit of real machines behind your back, transforming the recursion into iteration along the way. Except sometimes the translation isn't perfect, and then you notice because your performance goes down the drain. :) – hobbs Jul 05 '14 at 22:28
-
@hobbs I'm struggling a bit when choosing an approach to solve problems. While searching I came across this - http://www.cs.cornell.edu/info/courses/spring-98/cs211/lecturenotes/07-recursion.pdf. This paper says Mathematicians prefer Recursion and programmers without CS background favour iteration. Well some languages make use of memoization to solve the repeated memory function call slowness. Not sure how much it makes sense. – HalfWebDev May 24 '20 at 15:37
-
@hobbs So, isn't it good to code in that abstraction which I assume must be for a reason? Or is it okay to re-invent the wheel or to put the other way around to have more control over data structures using iteration. Then again in this, if I do choose Iteration, Am I not letting go of implicit stack frames offered via recursion. I have a lot more going...Can we please talk somwhere? – HalfWebDev May 24 '20 at 15:37
Try implementing depth-first search recursively and iteratively and tell me which one gave you an easier time of it. Or merge sort. For a lot of problems it comes down to explicitly maintaining your own stack vs. leaving your data on the function stack.
I can't speak to Haskell as I've never used it, but this is to address the more general part of the question posed in your title.

- 80,905
- 18
- 123
- 145
-
11+1 for comparing a manually-managed stack to the function call stack. I'd never thought of it that way. – Frank Farmer Feb 02 '10 at 16:18
-
+1 Was gonna say walking trees is much more elegant recursively, but you got there first. You can do it iteratively without a stack though if you have parent pointers. It's still not very beautiful :) – Skurmedel Feb 02 '10 at 16:29
-
1This does not answer the question. It is true that some problems are recursive by nature, but bot *all*, so why not allow iteration at all. – Baruch Jan 26 '14 at 08:42
-
1one thing that is is easier with iteration is aborting a DFS. With recursion, you need to thrown an exception, or use a boolean flag and check it every level. With iteration you can simply break out of the main loop. – TemplateRex Jul 21 '14 at 10:25
Haskell do not allow iteration because iteration involves mutable state (the index).

- 510,854
- 105
- 1,084
- 1,005
-
This is probably a stupid comment as I know nothing about Haskell, but isn't building a stack for recursive calls a form of mutable state? – James McMahon Feb 02 '10 at 16:13
-
3
-
7@James McMahon - no, that is definitely not mutable state. Stack frames don't share data; they each have their own copy. – danben Feb 02 '10 at 16:16
-
So the point isn't that it is immutable, it is that it is immutable across threads. – James McMahon Feb 02 '10 at 16:33
-
2@James McMahon: No, it is immutable even within a thread. Remember that a single thread can have many stack frames (one per function call that has not yet returned). Each of these has its own set of data that is not accessible from the body of any other function. – danben Feb 02 '10 at 16:46
-
3@James McMahon: Nothing to do with threads. Stack frames are an implementation detail of the language itself. It's way simpler: your code can't mutate the state. – Feb 02 '10 at 16:49
-
@James McMahon I think you are confusing the implementation of Haskell (which is written in a non-functional language, usually!) with the language itself. – Andrew Jaffe Feb 02 '10 at 17:58
-
I think that might be the true reason, granted a while loop does not have an index, and can be an immutable construct, it does still encourage the use of side effects and mutability. – Didier A. Jun 10 '16 at 01:56
As others have stated, there's nothing intrinsically less performant about recursion. There are some languages where it will be slower, but it's not a universal rule.
That being said, to me recursion is a tool, to be used when it makes sense. There are some algorithms that are better represented as recursion (just as some are better via iteration).
Case in point:
fib 0 = 0
fib 1 = 1
fib n = fib(n-1) + fib(n-2)
I can't imagine an iterative solution that could possibly make the intent clearer than that.

- 16,034
- 7
- 51
- 41
-
4Unless you've got some memoization going on under the hood, this is an exponential time algorithm. No amount of clarity and readability excuses this extreme a level of inefficiency. – dsimcha Feb 02 '10 at 19:16
-
8Really? Downvoted because an example created to show how recursion can be clearer is inefficient? Wow. I guess I'll point out that at least some languages do memoization automatically under the hood, specifically functional ones for which recursion is the expected way to do things. – RHSeeger Feb 02 '10 at 20:17
-
-
1@FabiánHerediaMontiel If there is no memoization, that is, the results of calling fib(x) are not cached, it is exponential. fib(n-1) will call fib(n-2), each of which will call fib(n-3) all the way down to fib(1). If you work in the opposite direction, and iteratively calculate fib(n) by calculating from fib(0) up to fib(n), then it is linear. This would be the dynamic programming approach, explained in more detail [here](http://algorithms.tutorialhorizon.com/introduction-to-dynamic-programming-fibonacci-series/) – nchen24 Feb 19 '16 at 01:37
-
@dsimcha That's not because of reflection though, if you make fib memoized, the algorithm is still as simple as above. – Didier A. Jun 10 '16 at 02:06
Here is some information on the pros & cons of recursion & iteration in c:
http://www.stanford.edu/~blp/writings/clc/recursion-vs-iteration.html
Mostly for me Recursion is sometimes easier to understand than iteration.

- 82,559
- 17
- 97
- 130
Several things:
- Iteration is not necessarily faster
- Root of all evil: encouraging something just because it might be moderately faster is premature; there are other considerations.
- Recursion often much more succinctly and clearly communicates your intent
- By eschewing mutable state generally, functional programming languages are easier to reason about and debug, and recursion is an example of this.
- Recursion takes more memory than iteration.

- 17,397
- 5
- 46
- 65
-
The root of all evil is PREMATURE optimization, and you missed the rest of the quote, thus completely negating it's purpose; recursion often causes exponential space requirements. That ain't premature to avoid. For reference: "We should forget about small efficiencies, say about 97% of the time: premature optimization is the root of all evil. Yet we should not pass up our opportunities in that critical 3%." – Alice Apr 18 '16 at 16:53
Iteration is just a special form of recursion.

- 137,316
- 36
- 365
- 468
-
in the end, in assembly everything is "recursively" called through procedure calls – raaj Jan 08 '14 at 02:45
Recursion is one of those things that seem elegant or efficient in theory but in practice is generally less efficient (unless the compiler or dynamic recompiler) is changing what the code does. In general anything that causes unnecessary subroutine calls is going to be slower, especially when more than 1 argument is being pushed/popped. Anything you can do to remove processor cycles i.e. instructions the processor has to chew on is fair game. Compilers can do a pretty good job of this these days in general but it's always good to know how to write efficient code by hand.

- 1
- 1
-
This is intellectually dishonest; subroutine or procedure calls need not cause overhead, and do not somehow indicate overhead. As well, the compiler need not change "what the code does"; note the "as-if" rule of C++. As long as the code results in the same side effects, return value, etc, the language almost certainly does not specify exactly what the code "does"; you are not a human assembler. Do not look at C code and assume you know what it turns into; it probably doesn't, and the language doesn't require it to. – Alice Apr 18 '16 at 16:52
-
@Alice Could you give a source and perhaps an example of your claim that "subroutine or procedure calls do not cause overhead?" – Zimano Jan 09 '18 at 14:32
I find it hard to reason that one is better than the other all the time.
Im working on a mobile app that needs to do background work on user file system. One of the background threads needs to sweep the whole file system from time to time, to maintain updated data to the user. So in fear of Stack Overflow , i had written an iterative algorithm. Today i wrote a recursive one, for the same job. To my surprise, the iterative algorithm is faster: recursive -> 37s, iterative -> 34s (working over the exact same file structure).
Recursive:
private long recursive(File rootFile, long counter) {
long duration = 0;
sendScanUpdateSignal(rootFile.getAbsolutePath());
if(rootFile.isDirectory()) {
File[] files = getChildren(rootFile, MUSIC_FILE_FILTER);
for(int i = 0; i < files.length; i++) {
duration += recursive(files[i], counter);
}
if(duration != 0) {
dhm.put(rootFile.getAbsolutePath(), duration);
updateDurationInUI(rootFile.getAbsolutePath(), duration);
}
}
else if(!rootFile.isDirectory() && checkExtension(rootFile.getAbsolutePath())) {
duration = getDuration(rootFile);
dhm.put(rootFile.getAbsolutePath(), getDuration(rootFile));
updateDurationInUI(rootFile.getAbsolutePath(), duration);
}
return counter + duration;
}
Iterative: - iterative depth-first search , with recursive backtracking
private void traversal(File file) {
int pointer = 0;
File[] files;
boolean hadMusic = false;
long parentTimeCounter = 0;
while(file != null) {
sendScanUpdateSignal(file.getAbsolutePath());
try {
Thread.sleep(Constants.THREADS_SLEEP_CONSTANTS.TRAVERSAL);
} catch (InterruptedException e) {
e.printStackTrace();
}
files = getChildren(file, MUSIC_FILE_FILTER);
if(!file.isDirectory() && checkExtension(file.getAbsolutePath())) {
hadMusic = true;
long duration = getDuration(file);
parentTimeCounter = parentTimeCounter + duration;
dhm.put(file.getAbsolutePath(), duration);
updateDurationInUI(file.getAbsolutePath(), duration);
}
if(files != null && pointer < files.length) {
file = getChildren(file,MUSIC_FILE_FILTER)[pointer];
}
else if(files != null && pointer+1 < files.length) {
file = files[pointer+1];
pointer++;
}
else {
pointer=0;
file = getNextSybling(file, hadMusic, parentTimeCounter);
hadMusic = false;
parentTimeCounter = 0;
}
}
}
private File getNextSybling(File file, boolean hadMusic, long timeCounter) {
File result= null;
//se o file é /mnt, para
if(file.getAbsolutePath().compareTo(userSDBasePointer.getParentFile().getAbsolutePath()) == 0) {
return result;
}
File parent = file.getParentFile();
long parentDuration = 0;
if(hadMusic) {
if(dhm.containsKey(parent.getAbsolutePath())) {
long savedValue = dhm.get(parent.getAbsolutePath());
parentDuration = savedValue + timeCounter;
}
else {
parentDuration = timeCounter;
}
dhm.put(parent.getAbsolutePath(), parentDuration);
updateDurationInUI(parent.getAbsolutePath(), parentDuration);
}
//procura irmao seguinte
File[] syblings = getChildren(parent,MUSIC_FILE_FILTER);
for(int i = 0; i < syblings.length; i++) {
if(syblings[i].getAbsolutePath().compareTo(file.getAbsolutePath())==0) {
if(i+1 < syblings.length) {
result = syblings[i+1];
}
break;
}
}
//backtracking - adiciona pai, se tiver filhos musica
if(result == null) {
result = getNextSybling(parent, hadMusic, parentDuration);
}
return result;
}
Sure the iterative isn't elegant, but alhtough its currently implemented on an ineficient way, it is still faster than the recursive one. And i have better control over it, as i dont want it running at full speed, and will let the garbage collector do its work more frequently.
Anyway, i wont take for granted that one method is better than the other, and will review other algorithms that are currently recursive. But at least from the 2 algorithms above, the iterative one will be the one in the final product.

- 135
- 1
- 9
I don't think there's anything intrinsically less performant about recursion - at least in the abstract. Recursion is a special form of iteration. If a language is designed to support recursion well, it's possible it could perform just as well as iteration.
In general, recursion makes one be explicit about the state you're bringing forward in the next iteration (it's the parameters). This can make it easier for language processors to parallelize execution. At least that's a direction that language designers are trying to exploit.

- 333,147
- 50
- 533
- 760
-
It is worth noting that "special form" does not mean one is a subset of the other. All iteration can be converted to recursion, and of course vice-versa. – semicolon Apr 17 '16 at 20:40
In Java, recursive solutions generally outperform non-recursive ones. In C it tends to be the other way around. I think this holds in general for adaptively compiled languages vs. ahead-of-time compiled languages.
Edit: By "generally" I mean something like a 60/40 split. It is very dependent on how efficiently the language handles method calls. I think JIT compilation favors recursion because it can choose how to handle inlining and use runtime data in optimization. It's very dependent on the algorithm and compiler in question though. Java in particular continues to get smarter about handling recursion.
Quantitative study results with Java (PDF link). Note that these are mostly sorting algorithms, and are using an older Java Virtual Machine (1.5.x if I read right). They sometimes get a 2:1 or 4:1 performance improvement by using the recursive implementation, and rarely is recursion significantly slower. In my personal experience, the difference isn't often that pronounced, but a 50% improvement is common when I use recursion sensibly.
-
can link some empirical data to support this? Very curious to see numbers. – wheaties Feb 02 '10 at 19:17
-
1I've added a link to a small study. It's not fully constant, but seems to jibe with my Java experience that small, recursive methods beat long, iterative ones. Repeated, recursive method calls very much favor good JITing of the method. – BobMcGee Feb 02 '10 at 19:39
-
As a low level ITERATION deals with the CX registry to count loops, and of course data registries. RECURSION not only deals with that it also adds references to the stack pointer to keep references of the previous calls and then how to go back.-
My University teacher told me that whatever you do with recursion can be done with Iterations and viceversa, however sometimes is simpler to do it by recursion than Iteration (more elegant) but at a performance level is better to use Iterations.-

- 5,509
- 7
- 39
- 47
I think it would help to get some understanding of what performance is really about. This link shows how a perfectly reasonably-coded app actually has a lot of room for optimization - namely a factor of 43! None of this had anything to do with iteration vs. recursion.
When an app has been tuned that far, it gets to the point where the cycles saved by iteration as against recursion might actually make a difference.

- 1
- 1

- 40,059
- 14
- 91
- 135
Recursion is the typical implementation of iteration. It's just a lower level of abstraction (at least in Python):
class iterator(object):
def __init__(self, max):
self.count = 0
self.max = max
def __iter__(self):
return self
# I believe this changes to __next__ in Python 3000
def next(self):
if self.count == self.max:
raise StopIteration
else:
self.count += 1
return self.count - 1
# At this level, iteration is the name of the game, but
# in the implementation, recursion is clearly what's happening.
for i in iterator(50):
print(i)

- 55,146
- 59
- 179
- 257
Iteration is more performant than recursion, right?
Yes.
However, when you have a problem which maps perfectly to a Recursive Data Structure, the better solution is always recursive.
If you pretend to solve the problem with iterations you'll end up reinventing the stack and creating a messier and ugly code, compared to the elegant recursive version of the code.
That said, Iteration will always be faster than Recursion. (in a Von Neumann Architecture), so if you use recursion always, even where a loop will suffice, you'll pay a performance penalty.

- 1
- 1

- 5,639
- 2
- 31
- 30
I would compare recursion with an explosive: you can reach big result in no time. But if you use it without cautions the result could be disastrous.
I was impressed very much by proving of complexity for the recursion that calculates Fibonacci numbers here. Recursion in that case has complexity O((3/2)^n) while iteration just O(n). Calculation of n=46 with recursion written on c# takes half minute! Wow...
IMHO recursion should be used only if nature of entities suited for recursion well (trees, syntax parsing, ...) and never because of aesthetic. Performance and resources consumption of any "divine" recursive code need to be scrutinized.

- 393
- 1
- 5
- 12
"Iteration is more performant than recursion" is really language- and/or compiler-specific. The case that comes to mind is when the compiler does loop-unrolling. If you've implemented a recursive solution in this case, it's going to be quite a bit slower.
This is where it pays to be a scientist (testing hypotheses) and to know your tools...

- 49,173
- 15
- 109
- 139
on ntfs UNC max path as is 32K
C:\A\B\X\C.... more than 16K folders can be created...
But you can not even count the number of folders with any recursive method, sooner or later all will give stack overflow.
Only a Good lightweight iterative code should be used to scan folders professionally.
Believe or not, most top antivirus cannot scan maximum depth of UNC folders.