9.6. Recursively Defined Data
While the data we've processed with references up to this point has been rather fixed structure, sometimes we have to deal with hierarchical data, which is often defined recursively.
For Example One, consider an HTML table that has rows containing cellsand some of those cells may also contain entire tables. Example Two could be a visual representation of a filesystem consisting of directories containing files and other directories. Example Three is a company organization chart, which has managers with direct reports, some of whom may be managers themselves. And Example Four is a more complex organization chart, which can contain instances of the HTML tables of Example One, the filesystem representations of Example Two, or even entire organization charts . . . .
We can use references to acquire, store, and process such hierarchical information. Frequently, the routines to manage the data structures end up as recursive subroutines.
Recursive algorithms deal with the unlimited complexity of their data by beginning with a base case and building upon that. The base case considers what to do in the simplest case: when the leaf node has no branches, when the array is empty, when the counter is at zero. In fact, it's common to have more than one base case in various branches of a recursive algorithm. A recursive algorithm with no base case is an infinite loop.
A recursive subroutine has a branch from which it calls itself to handle a portion of the task, and a branch that doesn't call itself to handle the base cases. In Example One above, the base case could be a table cell that is empty. There could also be base cases for empty tables and table rows. In Example Two, base cases would be needed for files, and perhaps for empty directories.
For example, a recursive subroutine handling the factorial function
, which is one of the simplest recursive functions, might look like:
sub factorial {
my $n = shift;
if ($n <= 1) {
return 1;
} else {
return $n * factorial($n  1);
}
}
Here we have a base case where $n is less than or equal to 1, which does not invoke the recursive instance, along with a recursive case for $n greater than 1, which calls the routine to handle a portion of the problem (i.e., compute the factorial of the next lower number).
This task would probably be solved better using iteration rather than recursion, even though the classic definition of factorial is often given as a recursive operation.
