Is tail recursion when a recursive procedure describes an iterative process? - recursion

Is tail recursion when a recursive procedure describes an iterative process? If not could you tell me where I've gone wrong?

Yes. For it to be iterative it needs to only consist of tail calls or some other looping construct like tail calls.

Tail recursive function is one in which the recursive call is the last executed line of the code in the function.

Related

Tail recursion without tail call optimization

Let say we had two versions of a recursive function, with one of them being tail-recursive. Is there any benefit in using the function tail recursive if the language being used does not have tail-call optimization? From my understanding, without the optimization, each version of a function (tail and non-tail) would use the same number of stack frames (in most cases).
I know that in some cases, like the Fibonacci function for example, using a tail call can be more efficient even without tail-call optimization since it avoids double calls. But what if neither version of the function makes double calls? Would the tail-recursive function still be more efficient?
The answer to that question is hardware and language implementation dependent. In most cases, however, I'd have to think that a simple GOTO is faster than CALL-RETURN instruction pair.

Problems understanding if the following is a tail-recursive function

Quoting from wikipedia
...a tail call is a subroutine call performed as the final action of a procedure. If a tail call might lead to the same subroutine being called again later in the call chain, the subroutine is said to be tail-recursive, which is a special case of recursion.
Now I've the following routine written in C
int foo (int x){
if ( x > 100)
return x-10;
else
return foo(foo(x+11));
}
Based on the definition above, it seems to me that foo should be a tail recursive function since it recursive call is the final action of the procedure, but somewhere I've once read that this is not a tail recursive function.
Hence the question:
why isn't this function tail-recursive?
This function is typically not considered tail-recursive, because it involves multiple recursive calls to foo.
Tail recursion is particularly interesting because it can be trivially rewritten (for example by a compiler optimization) into a loop. It is not possible to completely eliminate recursion with this tail-call-optimization technique in your example, and thus one would not consider this function as tail-recursive, even if its last statement is a recursive call.

Tail Recursion vs Forward recursion in Erlang

Is tail recursion better than forward recursion for perfomance in erlang?
Or erlang compiler optimizes forward recursion too?
I mean, are there any reasons to use tail recursion instead of forward recursion?
In my opinion, forward recursion looks more pretty.
Tail recursion and forward recursion are totally different concepts.
See this discussion.
It is possible to write a forward recursion that is tail recursive, and thus optimized. It is also possible to write a forward recursion that is not tail recursive: in this case, it will not be optimized, i.e. it will consume stack space.
Tail recursion is usually better because it uses less memory. You only bring what you need onto the next call, which minimizes memory utilization on the stack. Also, when the tail recursive code is optimized, function returns that are not needed are thrown away which will make it slightly faster in some cases.
For example, if a function's return value is the call to another function, there is no need to keep the intermediary function on the stack. So the code jumps back directly to the caller from the inner function.
Non-tail recursion is optimized to tail recursion in some cases by the Erlang compiler, but don't count on it. Make it a good habit to code tail recursive functions whenever you can.

Is there any limit to recursion in lisp?

I enjoy using recursion whenever I can, it seems like a much more natural way to loop over something then actual loops. I was wondering if there is any limit to recursion in lisp? Like there is in python where it freaks out after like 1000 loops?
Could you use it for say, a game loop?
Testing it out now, simple counting recursive function. Now at >7000000!
Thanks alot
First, you should understand what tail call is about.
Tail call are call that do not consumes stack.
Now you need to recognize when your are consuming stack.
Let's take the factorial example:
(defun factorial (n)
(if (= n 1)
1
(* n (factorial (- n 1)))))
Here is the non-tail recursive implementation of factorial.
Why? This is because in addition to a return from factorial, there is a pending computation.
(* n ..)
So you are stacking n each time you call factorial.
Now let's write the tail recursive factorial:
(defun factorial-opt (n &key (result 1))
(if (= n 1)
result
(factorial-opt (- n 1) :result (* result n))))
Here, the result is passed as an argument to the function.
So you're also consuming stack, but the difference is that the stack size stays constant.
Thus, the compiler can optimize it by using only registers and leaving the stack empty.
The factorial-opt is then faster, but is less readable.
factorial is limited to the size of the stack will factorial-opt is not.
So you should learn to recognize tail recursive function in order to know if the recursion is limited.
There might be some compiler technique to transform a non-tail recursive function into a tail recursive one. Maybe someone could point out some link here.
Scheme mandates tail call optimization, and some CL implementations offer it as well. However, CL does not mandate it.
Note that for tail call optimization to work, you need to make sure that you don't have to return. E.g. a naive implementation of Fibonacci where there is a need to return and add to another recursive call, will not be tail call optimized and as a result you will run out of stack space.

Difference between recursion and iteration

What is the difference? Are these the same? If not, can someone please give me an example?
MW:
Iteration - 1 : the action or a process of iterating or repeating: as a : a procedure in which repetition of a sequence of operations yields results successively closer to a desired result b : the repetition of a sequence of computer instructions a specified number of times or until a condition is met
Recursion - 3 : a computer programming technique involving the use of a procedure, subroutine, function, or algorithm that calls itself one or more times until a specified condition is met at which time the rest of each repetition is processed from the last one called to the first
We can distinguish (as is done in SICP) recursive and iterative procedures from recursive and iterative processes. The former are as your definition describes, where recursion is basically the same as mathematical recursion: a recursive procedure is defined in terms of itself. An iterative procedure repeats a block of code with a loop statement. A recursive process, however, is one that takes non-constant (e.g. O(n) or O(lg(n)) space) to execute, while an iterative process takes O(1) (constant) space.
For mathematical examples, the Fibonacci numbers are defined recursively:
Sigma notation is analogous to iteration:
as is Pi notation. Similar to how some (mathematical) recursive formulae can be rewritten as iterative ones, some (but not all) recursive processes have iterative equivalents. All recursive procedures can be transformed into iterative ones by keeping track of partial results in your own data structure, rather than using the function call stack.
[Hurry and trump this!]
One form can be converted to the other, with one notable restriction: many "popular" languages (C/Java/normal Python) do not support TCO/TCE (tail-call-optimization/tail-call-elimination) and thus using recursion will 'add extra data to the stack' each time a method calls itself recursively.
So in C and Java, iteration is idiomatic, whereas in Scheme or Haskell, recursion is idiomatic.
As per the definitions you mentioned, these 2 are very different. In iteration, there is no self-calling, but in recursion, a function calls itself
For example. Iterative algorithm for factorial calculation
fact=1
For count=1 to n
fact=fact*count
end for
And the recursive version
function factorial(n)
if (n==1) return 1
else
n=n*factorial(n-1)
end if
end function
Generally
Recursive code is more succinct but uses a larger amount of memory. Sometimes recursion can be converted to iterations using dynamic programming.
Here's a Lisp function for finding the length of a list. It is recursive:
(defun recursive-list-length (L)
"A recursive implementation of list-length."
(if (null L)
0
(1+ (recursive-list-length (rest L)))))
It reads "the length of a list is either 0 if that list is empty, or 1 plus the length of the sub-list starting with the second element).
And this is an implementation of strlen - the C function finding the length of a nul-terminated char* string. It is iterative:
size_t strlen(const char *s)
{
size_t n;
n = 0;
while (*s++)
n++;
return(n);
}
You goal is to repeat some operation. Using iteration, you employ an explicit loop (like the while loop in the strlen code). Using recursion, your function calls itself with (usually) a smaller argument, and so on until a boundary condition (null L in the code above) is met. This also repeats the operation, but without an explicit loop.
Recursion:
Eg: Take fibonacci series for example. to get any fibonacci number we have to know the previous one. So u will berform the operation (same one) on every number lesser than the given and each of this inturn calling the same method.
fib(5) = Fib (4) + 5
fib(4) = Fib (3) + 4
.
.
i.e reusing the method fib
Iteration is looping like you add 1+1+1+1+1(iteratively adding) to get 5 or 3*3*3*3*3 (iteratively multiplying)to get 3^5.
For a good example of the above, consider recursive v. iterative procedures for depth-first search. It can be done using language features via recursive function calls, or in an iterative loop using a stack, but the process is inherently recursive.
For difference between recursive vs non-recursive;
recursive implementations are a bit easier to verify for correctness; non-
recursive implementations are a bit more efficient.
Algorithms (4th Edition)

Resources