0

I have a Perl data structurte like so

%myhash = (
  k1 => v1, 
  kArray => [
    {
      name => "anonymous hash",
      ...
    },
    \&funcThatReturnsHash,
    {
      name => "another anonymous hash",
      ...
    }
  ]
);

Elsewhere I iterate through the list in kArray which contains a bunch of hashes. I would like to either process the actual hash OR the hash returned by the function.

foreach my $elem( @{myhash{kArray}} ) {

  if (ref($elem) == "CODE") {
     %thisHash = &$elem;
  }
  else {
     %thisHash = %$elem;
  }
  ...
}

However ref ($elem) is always scalar or undefined. I tried func, &func, \&func, \%{&func}, in %myhash to no effect.

how do I extract the hash within the function in the main body?

0

2 Answers 2

2

Apart from the code sample you give being invalid Perl, the main problems seem to be that you are using == to compare strings instead of eq, and you are assigning a hash reference to a hash variable %thishash. I assure you that ref $elem never returns SCALAR with the data you show

It would help you enormously if you followed the common advice to use strict and use warnings at the top of your code

This will work for you

for my $elem ( @{ $myhash{kArray} } ) {

    my $this_hash;

    if ( ref $elem eq 'CODE' ) {
         $this_hash = $elem->();
    }
    else {
         $this_hash = $elem;
    }

    # Do stuff with $this_hash
}

or you could just use a map like this

use strict;
use warnings;
use 5.010;

use Data::Dump;

my %myhash = (
    k1     => v1,
    kArray => [
        {
            name => "anonymous hash",
        },
        \&funcThatReturnsHash,
        {
            name => "another anonymous hash",
        }
    ]
);

for my $hash ( map { ref eq 'CODE' ? $_->() : $_ } @{ $myhash{kArray} } ) {
  say $hash->{name};
}


sub funcThatReturnsHash {
    {  name => 'a third anonymous hash' };
}

output

anonymous hash
a third anonymous hash
another anonymous hash
Sign up to request clarification or add additional context in comments.

Comments

1

If you turn on strict and warnings, you'll see that:

foreach my $elem(@{mynahs{kArray}}) {

Isn't valid. You need at the very least a $ before mynahs.

But given something like this - your approach works - here's an example using map to 'run' the code references:

#!/usr/bin/perl
use strict;
use warnings;
use Data::Dumper;

sub gimme_hash {
    return { 'fish' => 'paste' };
}

my $stuff =
    [ { 'anon1' => 'value' }, 
      \&gimme_hash, 
      { 'anon2' => 'anothervalue' }, ];

my $newstuff = [ map { ref $_ eq "CODE" ? $_->() : $_ } @$stuff ];
print Dumper $newstuff;

Turns that hash into:

$VAR1 = [
          {
            'anon1' => 'value'
          },
          {
            'fish' => 'paste'
          },
          {
            'anon2' => 'anothervalue'
          }
        ];

But your approach does work:

foreach my $element ( @$stuff ) {
   my %myhash;
   if ( ref $element eq "CODE" ) {
      %myhash = %{$element -> ()}; 
   }
   else {
      %myhash = %$element;
   }
   print Dumper \%myhash; 
}

Gives:

$VAR1 = {
          'anon1' => 'value'
        };
$VAR1 = {
          'fish' => 'paste'
        };
$VAR1 = {
          'anon2' => 'anothervalue'
        };

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.