views:

490

answers:

6

If not, is there a good counter example that shows an iterative algorithm for which there exists no recursive counterpart?

If it is the case that all iterative algorithms can be expressed recursively, are there cases in which this is more difficult to do?

Also, what role does the programming language play in all this? I can imagine that Scheme programmers have a different take on iteration (= tail-recursion) and stack usage than Java-only programmers.

+20  A: 

There's a simple ad hoc proof for this. Since you can build a Turing complete language using strictly iterative structures and a Turning complete language using only recursive structures, then the two are therefore equivalent.

plinth
Wow, food for thought. I envy all the upvoters that digested this more quickly than I did. Time to read up on this.
eljenso
Wait, isn't that a logical fallacy? Circular reasoning?
C Bauer
C Bauer: Actually, it is not. The proof is very easy to do: assume languages IT (with iterative constructs only) and REC (with recursive constructs only). Simulate a universal turing machine using IT, then simulate a universal turing machine using REC. The existence of the simulator programs guarantees that both IT and REC can calculate all the computable functions. This property is proven for the lambda calculus, where all functions are partial recursive.
fishlips
Alternately, build a Turing complete language using strictly (iteration/recursion), and in it write an interpreter for a Turing complete language using strictly (recursion/iteration). Voila, whatever program you've written is being executed iteratively and recursively, simultaneously!
David Thornley
+6  A: 

Like you say, every iterative approach can be turned into a "recursive" one, and with tail calls, the stack will not explode either. :-) In fact, that's actually how Scheme implements all common forms of looping. Example in Scheme:

(define (fib n)
  (do ((x 0 y)
       (y 1 (+ x y))
       (i 1 (+ i 1)))
      ((> i n) x)))

Here, although the function looks iterative, it actually recurses on an internal lambda that takes three parameters, x, y, and i, and calling itself with new values at each iteration.

Here's one way that function could be macro-expanded:

(define (fib n)
  (letrec ((inner (lambda (x y i)
                    (if (> i n) x
                        (inner y (+ x y) (+ i 1))))))
    (inner 0 1 1)))

This way, the recursive nature becomes more visually apparent.

Chris Jester-Young
And do note that *any* iterative algorithm can be turned into a tail-recursive algorithm. For instance, just transform it to continuation-passing style.
Derrick Turk
I would just add that not every language compiler optimizes tail calls, so the stack can indeed "explode" (overflow) in those languages using tail recursion (ex. C#).
dcstraw
+4  A: 

Defining iterative as:

function q(vars):
  while X:
    do Y

Can be translated as:

 function q(vars):
    if X:
      do Y
      call q(vars)

Y in most cases would include incrementing a counter that is tested by X. This variable will have to be passed along in 'vars' in some way when going the recursive route.

Johan
A: 

Prolog is recursive only language and you can do pretty much everything in it (I don't suggest you do, but you can :))

dmonlord
+1  A: 

As noted by plinth in the their answer we can construct proofs showing how recursion and iteration are equivalent and can both be used to solve the same problem; however, even though we know the two are equivalent there are drawbacks to use one over the other.

In languages that are not optimized for recursion you may find that an algorithm using iteration preforms faster than the recursive one and likewise, even in optimized languages you may find that an algorithm using iteration written in a different language runs faster than the recursive one. Furthermore, there may not be an obvious way of written a given algorithm using recursion versus iteration and vice versa. This can lead to code that is difficult to read which leads to maintainability issues.

Rob
+3  A: 
Norman Ramsey