Procedure Recursion and Stacking - recursion

To model the run-time semantics of procedures, it is known that a stack is generally needed.
1. If the language does not allow procedure recursion, do we have to have stacks?
2. If the language does allow procedure recursion, but a recursive call can only happen at the end of a procedure, do we have to have stacks?

No. However if the language is turing complete you can simulate one if you want. Eg. Brainf**k doesn't have a stack and I have made a LISP1 interpreter with it that supports procedures and macros.
It depends. Traditionally you need a way to have multiple nested arguments and that is a stack by definition. If your procedures have no arguments and only can call something else in the end of it's code It's almost as if procedures give less value than a goto would. However if you mean tail instead of end then it would be just as good as a goto without arguments.

Related

Is explicit stack better than recursion

We can print a linked list in reverse order with a stack as well as using recursion. My teacher said that using explicit stack is better since recursion also uses stack but has to maintain a lot of other parameters. Even if we use std::stack from stack, doesn't referring to an external library also take up time? How does using an explicit stack save time/space compared to using a recursive solution?
Recursion involves the use of implicit stacks. This is implemented in the background by the compiler being used to compile your code.
This background stack created by the compiler is known as a ‘Call stack’. Call Stack can be implemented using stack data structure which stores information about the active subroutines of a computer program.
Each subroutine call uses a frame inside the call stack called the stack frame. When a function returns a value, it’s stack frame is popped off the call stack.
Recursion's Call Stack vs Explicit Call Stack?
Stack overflow
The fundamental difference between the 2 stacks is that the space allocated by the compiler for the call stack of a program is fixed. This means there will be a stack overflow if you’re not sure about the maximum no. of recursive function calls expected and there are way too many calls than the space allocated to the stack can handle at a given point of time.
On the other hand, if you define an explicit stack, it’s implemented on the heap space allocated to the program by the compiler at run time. And guess what, the heap size is not fixed and can increase dynamically during run-time when required. You don’t really have to worry about the explicit stack overflowing.
Space and Time
Which one will be faster for a given situation?
Iterating on an explicit stack can be faster than recursion in languages that don’t support recursion related optimizations such as tail call optimization for tail recursion.
What’s Tail recursion?
Tail recursion is a special case of recursion where the recursive function doesn’t do any more computation after the recursive function call i.e. the last step of the function is a call to the recursive function.
What’s Tail-call optimization (TCO)?
Tail-call optimization is where you are able to avoid allocating a new stack frame for a function because the calling function will simply return the value that it gets from the called function.
So, compilers/languages that support tail-call optimizations implement the call to the recursive function with only a single stack frame in the call stack. If your compiler/language doesn’t support this, then using an explicit stack will save you a LOT of space and time.
Python doesn’t support tail call optimization. The main reason for this is to have a complete and clear stack trace which enables efficient debugging. Almost all C/C++ compilers support tail call optimization.
Sometimes explicitly controlling the stack helps simplify things when multiple parameters are being used.
whereas, a recursive solution makes the size of the source code a lot smaller and more maintainable.
Conclusion
In the end, There’s no fixed answer. For a particular scenario, many factors need to be considered such as scalability, code maintainability, language/compiler being used, etc.
The best way would be to implement the solution using both ways, time the 2 solutions on an input set and analyze peak space utilization before deploying it on a production setup.
See Wikipedia - Recursion versus Iteration

Can't understand why is prolog looping infinitly

From Bratko's book, Prolog Programming for Artificial Intelligence (4th Edition)
We have the following code which doesn't work -
anc4(X,Z):-
anc4(X,Y),
parent(Y,Z).
anc4(X,Z):-
parent(X,Z).
In the book, on page 55, figure 2.15, is shown that parent(Y,Z) is kept calling until stack is out of memory.
What I don't understand is that prolog does a recursiv call to anc4(X,Y), and not to parent (Y,Z) first. Why doesn't prolog goes over and over to the first line, anc4(X,Y), and rather goes to the second line?
Can you please elaborate why is the line parent(Y,Z) is kept being called?
Thank you.
The origin of your 'problem' (i.e. goals order) is deeply rooted in the basic of the language.
Prolog is based on the simple and efficient strategy of chronological backtracking, to implement SLD resolution, and left recursive clauses, like anc4/2, cause an infinite recursion.
Indeed, the comma operator (,)/2 stands for
evaluate the right expression only if the left expression holds
So, order of goals in a clause is actually an essential part of the program.
For your concrete case,
... , parent(Y,Z).
cannot be called if
anc4(X,Y),
doesn't hold.
The counterpart to goals order is clauses order.
That is, the whole program has a different semantics after the clauses are exchanged:
anc4(X,Z):-
parent(X,Z).
anc4(X,Z):-
anc4(X,Y),
parent(Y,Z).
To better understand the problem, I think it's worth to try this definition as well.
Prolog cannot handle left recursion by default without a tabling mechanism. Only some Prolog systems support tabling and usually you need to explicitly declare which predicates are tabled.
If you're using e.g. XSB, YAP, or SWI-Prolog, try adding the following directive on top of your source file containing the definition for the anc4/2 predicate:
:- table(anc4/2).
and retry your queries. The tabling mechanism detects when a query is calling a variant (*) of itself and suspends execution of that branch until a query answer is found and tries an alternative branch (provided in your case by the second clause). If that happens, execution is resumed with that answer.
(*) Variant here means that two terms are equal upon variable renaming.

Memory management without stack?

To model the run-time semantics of procedures, it is known that a stack is generally needed.
If the language does not allow procedure recursion, do we have to have stacks?
And if the language does allow procedure recursion, but a recursive call can only happen at the end of a procedure, do we have to have stacks?
In Fortran, which you are probably interested in as an example, you do need stack for recursion. It is because you want local variables of recursive procedures to be independent for each invocation of the procedure. Not all have to be independent, but you generally want to have this possibility.
Without recursion, you have only one invocation of any procedure at any time so local variables can be static. Not so with recursion, you don't know how deep it will be so you need some dynamic data structure to store the data. You could emulate the stack on the heap if necessary, but you do need some dynamic memory.
Often, stack is also used for automatic (variable length) arrays, but that is not required, they can be on the heap depending on the compiler and its settings.
Stack is used to store return address to reach after a method ends execution.
Stack is also used to allocate objects with limited duration scope.
So, if your launguage does not permit automatic (C style) objects (or in other words, does not permit local scopes) or does not permit methods, I suppose language could omit stack implementation completely.
I think recursion doesn't have anything to do with requirement of stack.

Can every recursive process be transformed into an iterative process?

I was reading the book, Structure and Interpretation of Computer Programs, where in it tells about the distinction between a recursive procedure and recursive process, and similarly between iterative procedure and iterative process. So, a recursive procedure could still generate an iterative process.
My question is: given a procedure which generates a recursive process, can you always write another procedure that achieves the same result but generates an iterative process?
The specific problem that I was trying to solve was to write a procedure which does an in-order traversal of a binary search tree but generates an iterative process. I know how you can use a stack to get an iterative procedure for this problem. However, that still generates a recursive process (correct me if I am wrong here).
Thanks,
Abhinav.
Some tasks are truly impossible to solve with linear iterative processes (e.g. tree recursion, which is impossible to convert to tail recursion). You either have to use the stack built into your platform, or re-create it yourself within the language (usually a much less efficient and uglier solution).
So if you define 'recursion' as 'using a stack to store different invocations of the same code', then yes, recursion sometimes is absolutely required.
If you define 'recursion' as 'a function in my language (eventually) calling itself', then you can get by without explicit recursion by re-implementing recursiveness yourself, as describes above. This is only useful if your language doesn't provide recursive procedures, or not enough stack space, or has similar limitations. (For instance, early Fortran's didn't have recursive procedures. Of course, they also didn't have the dynamic data structures that you would need to simulate them! Personally, I have never come across an actual example where implementing pseudo-recursion was the right solution.)
Read this former SO post:
Design patterns for converting recursive algorithms to iterative ones
there are a lot of good answers there which may help you further.
Any tail recursive process can be transformed into an iterative one.
But not all recursive processes can be transformed into an iterative one.

Doubts in ada language involving procedures

I am a beginner in Ada and I have come across a piece of code which is shown below:
procedure Null_Proc is
begin
null;
end;
Now as per my knowledge the procedure in Ada doesn't return anything. My doubt is what does this procedure Null_proc do? I mean I am not clear with the definition of the procedure.
It does nothing.
It might be useful when a procedure must be called but nothing must be done; otherwise, it has little value. (I am working from memory; I assume that Ada does allow functions or procedures as parameters to other functions - in terms of C, pointers to functions.)
I've been known to write main routines that way when all the "real code" was in the withed packages. This is particularly likely if your program uses tasking, as the main routine cannot accept rendezvous like a task can, so it often ends up with nothing useful to do. Your entire program will stay active until all tasks complete, so the main routine really doesn't have to do anything.
Another possible use would be for implementing some kind of default routine to supply to callbacks.

Resources