Link Details

Link 8045 thumbnail
User 111696 avatar

By bloid
via saasblogs.com
Published: Nov 30 2006 / 18:15

The problem is, using recursion in practice through today’s popular languages (such as my favorite, C#) can prove to be a disaster. At a minimum, standard recursion proves to be inefficient. Worst case scenario, it’ll consume all of your available memory. So how can you reap the benefits of recursive elegance but avoid the side-effects?
  • 9
  • 0
  • 1207
  • 207

Comments

Add your comment
User 190346 avatar

ilazarte replied ago:

0 votes Vote down Vote up Reply

"Never hire anyone who codes a factorial function with recursion" ;)

User 179375 avatar

Ricky Clarkson replied ago:

0 votes Vote down Vote up Reply

Write me an iterative version. In Haskell.

User 111696 avatar

bloid replied ago:

0 votes Vote down Vote up Reply

fac n = snd (until ((>n) . fst) (\(i,m) -> (i+1, i*m)) (1,1))

?

from: http://www.willamette.edu/~fruehr/haskell/evolution.hs

User 179375 avatar

Ricky Clarkson replied ago:

0 votes Vote down Vote up Reply

Wow. I had to try that out to believe you. ;)

Much more readable as the recursive version anyway..

Here's rot13 in Haskell:

[chr(mod (ord a-ord 'a'+13) 26+ord 'a') | a <- "bushpx"]

..runs away

User 111696 avatar

bloid replied ago:

0 votes Vote down Vote up Reply

hehehe ;)

User 209613 avatar

MattGiuca replied ago:

1 votes Vote down Vote up Reply

The problem is, he's rewritten explicit recursion with implicit recursion - he's just using his own stack to do the recursion now instead of using the built-in call stack. Technically it's still recursion.

It's a little bit more efficient*, since it doesn't need to waste time OR space pushing and popping various registers, arguments and variables on the new stack frame. Also it's probably better because the memory is being allocated on the heap, not the stack, so there's more to go around. However, it's still recursive, and ultimately it will still eat up the memory (it's linear space instead of constant space).

*Note: I'm thinking about this in terms of C, I'm not sure how C# does things internally but I'm sure it's similar.

A better (but less general) approach would have been to identify tail recursion (and perhaps even use several techniques to create tail recursion, if not immediately visible), and then it's possible to convert it into a truly iterative case, taking constant space. (Read up on tail recursion).

Most good optimising compilers for any language will automatically identify obvious tail recursion and convert it into iteration for you. So often it is enough to just make your recursive calls tail-recursive, to ensure constant space.

Of course, not all algorithms can be made tail-recursive (an obvious example is QuickSort, which needs to recurse twice). In the case of QuickSort, the best optimisation would be to follow this article and make an explicit stack.

User 205047 avatar

Lowell Heddings replied ago:

0 votes Vote down Vote up Reply

Recursive functions are usually a pretty simple way to accomplish things quickly. One of the methods I use to make sure I don't end up running out of memory is passing in a maxdepth parameter, that ends the recursion.

It really depends on what you are trying to accomplish, though... I'm typically not needing to recurse more than a few levels.

Add your comment


Html tags not supported. Reply is editable for 5 minutes. Use [code lang="java|ruby|sql|css|xml"][/code] to post code snippets.

Voters For This Link (9)



Voters Against This Link (0)