Recursively printing data structures in Perl
oop, perl, recursion
Solution
- Always use `use strict`;
- To be a good boy, use `use warnings` as well.
- The names you use for subroutines should make it obvious what the subroutine does. "recurseErrors" kind of violates that principle. Yes, it does recurse. But what errors?
- On the first line of each subroutine you should declare and initialize any parameters. recurseErrors first declares $str and then declares its parameters.
- Don't mix shift and = @_ like you do in str()
- You might consider breaking up what is now called recurseErrors into specialized routines for handling arrays and hashes.
- There's no need to quote variables like you do on lines 99 and 109.
Apart from that I think your instructor had a bad day that day.
Problem
I am currently learning Perl. I have Perl hash that contains references to hashes and arrays. The hashes and arrays may in turn contain references to other hashes/arrays. I wrote a subroutine to parse the hash recursively and print them with proper indentation. Though the routine works as expected, my instructor was not convinced about the readability and elegance of the below code. I would really appreciate to get the views of Perl experts here on possible optimization of the below code. Here is my complete code snippet.. ``` # Array of Arrays $ref_to_AoA = [ [ "fred", "barney" ], [ "george", "jane", "elroy" ], [ "homer", "marge", "bart" ], ]; #Array of Hashes $ref_to_AoH = [ { husband => "barney", wife => "betty", son => "bamm bamm", }, { husband => "george", wife => "jane", son => "elroy", }, ]; # Hash of Hashes $ref_to_HoH = { flintstones => { husband => "fred", pal => "barney", }, jetsons => { husband => "george", wife => "jane", "his boy" => "elroy", # Key quotes needed. }, simpsons => { husband => "homer", wife => "marge", kid => "bart", }, }; # Hash which contains references to arrays and hashes $finalHash = { 'arrayofArrays' => $ref_to_AoA, 'arrayofHash' => $ref_to_AoH, 'hashofHash' => $ref_to_HoH, }; $string = str($finalHash); print "$string\n"; #------------------------------------------------------------------ sub str { my $hash = shift; my ($space, $newline, $delimiter) = @_; $space = "" unless (defined $space); $newline = "\n\n\n" unless (defined $newline); $delimiter = "\n--------------------------------------------" unless (defined $delimiter); my $str = ""; for (sort keys %{$hash}) { my $value = $hash->{$_}; $str .= "$newline$space$_ == $value$delimiter"; $str .= recurseErrors($value,$space); } $str; } #------------------------------------------------------------------ sub recurseErrors { my $str; my ($value,$space) = @_; my $ref = ref $value; if ($ref eq 'ARRAY') { my $i = 0; my $isEmpty = 1; my @array = @$value; $space .= "\t"; for my $a (@array) { if (defined $a) { $isEmpty = 0; $str .= "\n$space$_\[$i\] :"; $str .= recurseErrors($a,$space); } $i++; } $str .= "= { }" if ($isEmpty); } elsif ($ref eq 'HASH') { $space .= "\t"; for my $k (sort keys %$value) { if ( ( ref($value->{$k}) eq 'HASH') || (ref $value->{$k} eq 'ARRAY') ) { my $val = $value->{$k}; $str .= "\n\n$space$k == "; $str .= "$val"; } else { $str .= "\n$space$k == "; } $str .= recurseErrors($value->{$k},$space); } # we have reached a scalar (leaf) } elsif ($ref eq '') { $str .= "$value"; } $str } #------------------------------------------------------------------ ``` Output: ``` arrayofArrays == ARRAY(0x9d9baf8) -------------------------------------------- arrayofArrays[0] : arrayofArrays[0] :fred arrayofArrays[1] :barney arrayofArrays[1] : arrayofArrays[0] :george arrayofArrays[1] :jane arrayofArrays[2] :elroy arrayofArrays[2] : arrayofArrays[0] :homer arrayofArrays[1] :marge arrayofArrays[2] :bart arrayofHash == ARRAY(0x9d9bba8) -------------------------------------------- arrayofHash[0] : husband == barney son == bamm bamm wife == betty arrayofHash[1] : husband == george son == elroy wife == jane hashofHash == HASH(0x9da45f8) -------------------------------------------- flintstones == HASH(0x9d9bb48) husband == fred pal == barney jetsons == HASH(0x9d9bbf8) his boy == elroy husband == george wife == jane simpsons == HASH(0x9d9bc48) husband == homer kid == bart wife == marge ```