0
votes

I am passing an array of references by reference to a subroutine. When I try to deference it in a sub-routine, it gives a flattened hash. How can I fix this? I don't want to have a flat hash and I am unable determine the reason for this.

I am sure that I am making a mistake somewhere but not able to spot it. Any comments/suggestions are totally welcome! Looking forward to hear from this wonderful community! Thanks in advance.

updated problem statement: Basically I am looking to pass a hash by reference to a sub-routine. And my issue is that when I accept it in the subroutine with a scalar variable, and then I try to de-reference it with % symbol, I still get a flat hash.

update: There was a confusion.As I was checking whether my hash is flat or not - I checked only with print Dumper %hash when I should actually have actually checked with print Dumper \%hash. Lack of this piece of information caused this issue.

Script:

#!/usr/bin/perl

use strict ;
use warnings ;
use Data::Dumper ;

my %h = (moe => "joe", toe => "poe") ;
my @a = (1,2,3,4) ;

my @refs = \(%h,@a) ;

sub sample()
{
  my $ref = shift ;
  my @refs = @{$ref} ;
  print "What I got in the sub! Seems OK!!\n" ;
  print Dumper @refs, "\n" ;

  my %h = %{$refs[0]} ;
  my @a = @{$refs[1]} ;

  print "I am not able to dereference this :(. Please help!! Hash is flat :(\n" ;
  print Dumper %h ;
  print Dumper @a ;
}

&sample(\@refs) ;

OUTPUT:

23:34:17[Host@User]$ ./test.pl 
What I got in the sub! Seems OK!!
$VAR1 = {
          'moe' => 'joe',
          'toe' => 'poe'
        };
$VAR2 = [
          1,
          2,
          3,
          4
        ];
$VAR3 = '
';
I am not able to dereference this :(. Please help!! Hash is flat :(
$VAR1 = 'moe';
$VAR2 = 'joe';
$VAR3 = 'toe';
$VAR4 = 'poe';
$VAR1 = 1;
$VAR2 = 2;
$VAR3 = 3;
$VAR4 = 4;
1
You may like Data::Printer. If it's about inspecting data structures, it will be a lot easier to work with than Data::Dumper, which is for machine consumption. - simbabque
You have made things very complicated for yourself. You have a remarkable number of references and dereferences, and you are misusing subroutine prototypes and defeating them by calling with &. I can only imagine that this has been written as a "find all the errors" homework task. That would be fine, but please say so in your question. - Borodin
@simbabque: I've never understood the appeal of Data::Printer, can you explain? I've always preferred the output of Data::Dump to that of Data::Dumper, but only because its default output is more concise. There is also the option of JSON and YAML, and I don't see why yet another unparseable format is better than any of those. - Borodin
@Borodin I like it because it sorts hash keys, shows everything neatly and concisely, knows about class internals, inheritance, lists methods, and it's in color! I learned "debugging" with Data::Dumper and used it for a long time. I just feel that for when I have to read it, p is nicer. Maybe it's a preference, I'm not sure. But the other ones you mentioned are all for transferring data. DDP is for you reading it quickly, and only for that. - simbabque
@Borodin as long as we don't need to put <pre> around it I'm good with most if them. Whatever is available and gets the job done. :-) - simbabque

1 Answers

4
votes

There's nothing to fix. You have what you wanted. You have a hash in %h and an array in @a.

But Data::Dumper takes a list of arguments and it treats each of its arguments as a separate variable to dump. So when you pass either a hash or an array to Dumper(), they will be unrolled into a list and you'll get them displayed as separate variables.

If you want to see the structure of an array or a hash using Dumper(), you should pass in a reference to the data structure instead.

print Dumper \%h;
print Dumper \@a;

Of course, that's effectively what you're doing on your first call to Dumper().

print Dumper @refs;

I should also point out that you have a couple of errors in your code that (fortunately?) cancel each other out. You define your subroutine sample with an empty prototype (sample() { ... }) which means that you will get a fatal error if you pass it any arguments. But when you call the subroutine, you use an & (&sample(@refs)) and one of the effects of that is to turn off prototype checking - so it works even though you pass arguments to the subroutine.

Best to omit the prototype completely (sub sample { ... }) and call the subroutine without the ampersand (sample(@refs))).