The RECURSIVE clause is a program attribute that allows a COBOL program to call itself directly or indirectly. This enables recursive programming techniques where a program can solve problems by breaking them down into smaller, similar subproblems.
Recursive calls create multiple instances of the program on the call stack.
The RECURSIVE clause is specified in the PROGRAM-ID paragraph to indicate that the program can call itself.
1234567891011121314151617181920212223* Basic RECURSIVE clause syntax PROGRAM-ID. program-name IS RECURSIVE. * Examples PROGRAM-ID. FACTORIAL IS RECURSIVE. PROGRAM-ID. TREE-TRAVERSE IS RECURSIVE. PROGRAM-ID. FIBONACCI IS RECURSIVE. * Complete program structure IDENTIFICATION DIVISION. PROGRAM-ID. RECURSIVE-EXAMPLE IS RECURSIVE. ENVIRONMENT DIVISION. DATA DIVISION. WORKING-STORAGE SECTION. 01 COUNTER PIC 9(3) VALUE 0. 01 RESULT PIC 9(5) VALUE 0. PROCEDURE DIVISION. MAIN-PROCESS. PERFORM RECURSIVE-FUNCTION STOP RUN.
The RECURSIVE clause is specified in the PROGRAM-ID paragraph.
1234567891011121314151617181920212223242526* Direct recursion - program calls itself PROGRAM-ID. DIRECT-RECURSIVE IS RECURSIVE. PROCEDURE DIVISION. MAIN-PROCESS. IF COUNTER < 10 ADD 1 TO COUNTER CALL "DIRECT-RECURSIVE" END-IF. * Indirect recursion - program A calls program B, which calls program A PROGRAM-ID. PROGRAM-A IS RECURSIVE. PROCEDURE DIVISION. MAIN-PROCESS. IF CONDITION-MET CALL "PROGRAM-B" END-IF. PROGRAM-ID. PROGRAM-B IS RECURSIVE. PROCEDURE DIVISION. MAIN-PROCESS. IF OTHER-CONDITION CALL "PROGRAM-A" END-IF.
Both direct and indirect recursion require the RECURSIVE clause.
Storage Section | Behavior with RECURSIVE | Use Case |
---|---|---|
WORKING-STORAGE | Shared across all recursive calls | Global data, constants |
LOCAL-STORAGE | Unique to each recursive call | Local variables, parameters |
LINKAGE SECTION | Parameters passed to each call | Input/output parameters |
These examples demonstrate common recursive algorithms and their implementation using the RECURSIVE clause in COBOL.
123456789101112131415161718192021222324252627282930313233343536373839IDENTIFICATION DIVISION. PROGRAM-ID. FACTORIAL IS RECURSIVE. ENVIRONMENT DIVISION. DATA DIVISION. WORKING-STORAGE SECTION. 01 INPUT-NUMBER PIC 9(3). 01 FACTORIAL-RESULT PIC 9(8). LINKAGE SECTION. 01 N PIC 9(3). 01 RESULT PIC 9(8). PROCEDURE DIVISION USING N RETURNING RESULT. MAIN-PROCESS. * Base case: factorial of 0 or 1 is 1 IF N = 0 OR N = 1 MOVE 1 TO RESULT ELSE * Recursive case: n! = n × (n-1)! SUBTRACT 1 FROM N GIVING INPUT-NUMBER CALL "FACTORIAL" USING INPUT-NUMBER RETURNING FACTORIAL-RESULT MULTIPLY N BY FACTORIAL-RESULT GIVING RESULT END-IF EXIT PROGRAM. * Example usage PROGRAM-ID. FACTORIAL-TEST. WORKING-STORAGE SECTION. 01 TEST-NUMBER PIC 9(3) VALUE 5. 01 FACTORIAL-OF-5 PIC 9(8). PROCEDURE DIVISION. MAIN-PROCESS. CALL "FACTORIAL" USING TEST-NUMBER RETURNING FACTORIAL-OF-5 DISPLAY "Factorial of " TEST-NUMBER " is " FACTORIAL-OF-5 STOP RUN.
This example shows recursive factorial calculation with proper base case handling.
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849IDENTIFICATION DIVISION. PROGRAM-ID. FIBONACCI IS RECURSIVE. ENVIRONMENT DIVISION. DATA DIVISION. LINKAGE SECTION. 01 N PIC 9(3). 01 FIB-RESULT PIC 9(6). PROCEDURE DIVISION USING N RETURNING FIB-RESULT. MAIN-PROCESS. * Base cases: F(0) = 0, F(1) = 1 IF N = 0 MOVE 0 TO FIB-RESULT ELSE IF N = 1 MOVE 1 TO FIB-RESULT ELSE * Recursive case: F(n) = F(n-1) + F(n-2) CALL "FIBONACCI" USING (N - 1) RETURNING FIB-RESULT * Note: This is simplified; actual implementation would need * to handle the two recursive calls properly END-IF EXIT PROGRAM. * More efficient implementation using iteration PROGRAM-ID. FIBONACCI-ITERATIVE. WORKING-STORAGE SECTION. 01 N PIC 9(3). 01 FIB-RESULT PIC 9(6). 01 PREV-1 PIC 9(6) VALUE 0. 01 PREV-2 PIC 9(6) VALUE 1. 01 COUNTER PIC 9(3). PROCEDURE DIVISION USING N RETURNING FIB-RESULT. MAIN-PROCESS. IF N = 0 MOVE 0 TO FIB-RESULT ELSE IF N = 1 MOVE 1 TO FIB-RESULT ELSE PERFORM VARYING COUNTER FROM 2 BY 1 UNTIL COUNTER > N COMPUTE FIB-RESULT = PREV-1 + PREV-2 MOVE PREV-2 TO PREV-1 MOVE FIB-RESULT TO PREV-2 END-PERFORM END-IF EXIT PROGRAM.
Fibonacci demonstrates both recursive and iterative approaches.
1234567891011121314151617181920212223242526272829303132333435363738394041IDENTIFICATION DIVISION. PROGRAM-ID. TREE-TRAVERSE IS RECURSIVE. ENVIRONMENT DIVISION. DATA DIVISION. WORKING-STORAGE SECTION. 01 TREE-NODE. 05 NODE-VALUE PIC 9(3). 05 LEFT-CHILD PIC X(8). 05 RIGHT-CHILD PIC X(8). PROCEDURE DIVISION USING TREE-NODE. MAIN-PROCESS. * In-order traversal: left subtree, root, right subtree IF LEFT-CHILD NOT = SPACES CALL "TREE-TRAVERSE" USING LEFT-CHILD END-IF * Process current node DISPLAY "Node value: " NODE-VALUE IF RIGHT-CHILD NOT = SPACES CALL "TREE-TRAVERSE" USING RIGHT-CHILD END-IF EXIT PROGRAM. * Example tree structure 01 SAMPLE-TREE. 05 ROOT-NODE. 10 ROOT-VALUE PIC 9(3) VALUE 50. 10 ROOT-LEFT PIC X(8) VALUE "LEFT-NODE". 10 ROOT-RIGHT PIC X(8) VALUE "RIGHT-NODE". 05 LEFT-NODE. 10 LEFT-VALUE PIC 9(3) VALUE 30. 10 LEFT-LEFT PIC X(8) VALUE SPACES. 10 LEFT-RIGHT PIC X(8) VALUE SPACES. 05 RIGHT-NODE. 10 RIGHT-VALUE PIC 9(3) VALUE 70. 10 RIGHT-LEFT PIC X(8) VALUE SPACES. 10 RIGHT-RIGHT PIC X(8) VALUE SPACES.
Tree traversal naturally lends itself to recursive implementation.
Following these best practices ensures effective and safe use of recursive programming in COBOL applications.
Pitfall | Problem | Solution |
---|---|---|
Missing base case | Infinite recursion, stack overflow | Always define termination condition |
No progress toward base case | Infinite recursion | Ensure each call moves toward termination |
Using WORKING-STORAGE for local data | Data corruption between calls | Use LOCAL-STORAGE for local variables |
Deep recursion | Stack overflow | Limit depth or use iterative approach |
Poor performance | Excessive function call overhead | Consider iterative alternatives |
Use Case | Recursion Suitability | Reasoning |
---|---|---|
Tree/Graph traversal | Excellent | Natural recursive structure |
Divide-and-conquer | Good | Problem naturally breaks down |
Backtracking | Good | State management is natural |
Simple calculations | Poor | Iterative is usually better |
High-frequency operations | Poor | Performance overhead too high |
Usage | Syntax | Example |
---|---|---|
Program definition | PROGRAM-ID. name IS RECURSIVE | PROGRAM-ID. FACTORIAL IS RECURSIVE |
Direct recursion | CALL "program-name" | CALL "FACTORIAL" |
With parameters | CALL "program-name" USING param | CALL "FACTORIAL" USING N |
With return value | CALL "program-name" RETURNING result | CALL "FACTORIAL" RETURNING RESULT |
Local storage | LOCAL-STORAGE SECTION | For variables unique to each call |
1. What is the primary purpose of the RECURSIVE clause in COBOL?
2. Where is the RECURSIVE clause typically specified in a COBOL program?
3. What is required for a recursive program to work properly?
4. What is a potential risk of recursive programming in COBOL?
5. Which of the following is a common use case for recursive programming?
Understanding the CALL statement for program invocation.
Using LOCAL-STORAGE for recursive program data.
Program identification and attributes.
Working with subprograms and modular programming.
Programming principles and techniques.