1

I am working on a function which should recursively parse through the data structure passed into it and then print it out with indentation. Something like:

indent(foo=>{bar=>'baz'})
should print like:
foo
  bar : baz

indent(foo=>[a,b,c=>'d',e])
should print like
foo
  a
  b
  c:d
  e

I came across a post here on Stack Overflow with a very similar scenario using depth-first recursion, as well as this page about how to recurse through a Perl data structure.

However, I am unable to follow how the the inner sub works. Also, it does not indent/print for certain scenarios like:

[aa,xx=>'yy',rr]
Output:
  aa
  xx
  yy
  rr

This is the code I am trying to work with:

&expand_references2([aa,xx=>'yy',rr]);

sub expand_references2 {
  my $indenting = -1;
  my $inner; $inner = sub {
    my $ref = $_[0];
    my $key = $_[1];
    $indenting++;
    if(ref $ref eq 'ARRAY'){
      print '  ' x $indenting;
      printf("%s\n",($key) ? $key : '');
      $inner->($_) for @{$ref};
    }elsif(ref $ref eq 'HASH'){
      print '  ' x $indenting;
      printf("%s\n",($key) ? $key : '');
      for my $k(sort keys %{$ref}){
        $inner->($ref->{$k},$k);
      }
    }else{
      if($key){
        print '  ' x $indenting,$key,' => ',$ref,"\n";
      }else{
        print '  ' x $indenting,$ref,"\n";
      }
    }
    $indenting--;
  };
  $inner->($_) for @_;
}
Community
  • 1
  • 1
user2461335
  • 53
  • 1
  • 7
  • 2
    This question is based on a false premise. `[a,b,c=>'d',e]` will compile only without `use strict 'subs'` in place, and even then will raise a warning *Unquoted string may clash with future reserved word*. It is *identical* to `[ 'a', 'b', 'c', 'd', 'e' ]`. The only difference between `=>` and an ordinary comma is that it will implcitly quote its first parameter if it is a bareword – Borodin Mar 24 '16 at 22:44
  • 2
    You *must always* `use strict` and `use warnings 'all'` at the top of every Perl program you write. It is also wrong to call subroutines with an ampersand character `&`; that hasn't been good practice since Perl 5 arrived twenty-two years ago. Whatever tutorial you are using to learn Perl you should drop it and find a more recent one – Borodin Mar 24 '16 at 22:52
  • Borodin: Thanks, you are right. It did consider [a,b,c=>'d',e] as [ 'a', 'b', 'c', 'd', 'e' ] and did not indent. Also, It did not use strict subs which is why it compiled and predicted the result as a b c d e – user2461335 Mar 24 '16 at 22:52
  • 1
    Data::Dumper does exactly this; you can use it to show you what the output *should* look like. `perl -MData::Dumper -e'print Dumper [aa,xx=>"yy",rr]'` – ThisSuitIsBlackNot Mar 24 '16 at 22:55
  • 2
    Please don't add more questions to your post. If you have a new problem then you should open a new question – Borodin Mar 24 '16 at 23:05
  • Borodin: Sure, I will open a new question next time on. – user2461335 Mar 24 '16 at 23:09
  • @Borodin: Could you please clarify why it adds an extra newline after every key? – user2461335 Mar 24 '16 at 23:25

1 Answers1

1

This question is based on a false premise: [a, b, c => 'd', e] will compile only without use strict 'subs' in place, and even then will raise a warning

Unquoted string may clash with future reserved word

It is identical to [ 'a', 'b', 'c', 'd', 'e' ]

The only difference between a fat comma => and an ordinary comma is that it will implicitly quote its first parameter if it is a bareword

You must always use strict and use warnings 'all' at the top of every Perl program you write. It is also wrong to call subroutines with an ampersand character &; that hasn't been good practice since Perl 5 arrived twenty-two years ago. Whatever tutorial you are using to learn Perl you should drop it and find a more recent one

Borodin
  • 123,915
  • 9
  • 66
  • 138