Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

odd number of elements in anonymous hash

Tags:

perl

I'm trying to understand this Perl code...

If there is one stream it works, if there are 2 or more streams it warns with odd number of elements in anonymous hash. It seems to return an array in that case. How do I add the array elements correctly to @streams? It appears to add correctly for the HASH case in the if clause. Is the else clause bunk?

 my $x = $viewedProjectDataObj->{streams};

    if (ref($x) eq 'HASH') {
        push(@streams, $x->{id});
    } elsif (ref($x) eq 'ARRAY') {

        print "$x\n";
        print "@$x\n";
        my @array = @$x;
        foreach my $obj (@array) {
            print "in $obj\n";
            print Dumper( $obj);
            push(@streams,  ($obj->{id}) );
        }
    }

    print "streamcount " . @streams % 2;
    print Dumper(@streams);


    my $stream_defect_filter_spec = {
        'streamIdList' => @streams,
        'includeDefectInstances' => 'true',
        'includeHistory' => 'true',
    };

    my @streamDefects = $WS->get_stream_defects($defectProxy, \@cids,             $stream_defect_filter_spec);
    print Dumper(@streamDefects);

I'm adding the next lines...

if ($defectSummary->{owner} eq "Various") {
    foreach (@streamDefects) {
        if (exists($_->{owner})) {
            $defectSummary->{owner} = $_->{owner};
            last;
        }
    }
}

my $diref = $streamDefects[0]->{defectInstances};
if ($diref) {
    my $defectInstance;
    if (ref($diref) eq 'HASH') {
        $defectInstance = $diref;
    } elsif (ref($diref) eq 'ARRAY') {
        $defectInstance = @{$diref}[0];
    } else {
        die "Unable to handle $diref (".ref($diref).")";
    }

It now errors with

Web API returned error code S:Server: calling getStreamDefects: No stream found for name null. $VAR1 = -1; me Can't use string ("-1") as a HASH ref while "strict refs" in use at xyz-handler.pl line 317.

some Dumper output

$VAR1 = {
      'streamIdList' => [
                          {
                            'name' => 'asdfasdfadsfasdfa'
                          },
                          {
                            'name' => 'cpp-62bad47d63cfb25e76b29a4801c61d8d'

                          }
                        ],
      'includeDefectInstances' => 'true',
      'includeHistory' => 'true'
    };
like image 516
DB- Avatar asked Jul 21 '12 18:07

DB-


People also ask

What is anonymous hash?

An anonymous hash is simply a hash without a name. Both named and anonymous hashes have references, and \%hash is no more a direct reference than { foo => "bar" } . You imply that the latter is an indirect reference.

How do you check if a value exists in a hash Perl?

Perl | exists() Function The exists() function in Perl is used to check whether an element in an given array or hash exists or not. This function returns 1 if the desired element is present in the given array or hash else returns 0.


1 Answers

The list assigned to a hash is a set of key/value pairs, which is why the number of elements must be even.

Because the => operator is little more than a comma, and the @streams array is flattened in the list, this

my $stream_defect_filter_spec = {
  'streamIdList' => @streams,
  'includeDefectInstances' => 'true',
  'includeHistory' => 'true',
};

is equivalent to this

my $stream_defect_filter_spec = {
  'streamIdList' => $streams[0],
  $streams[1] => $streams[2],
  $streams[3] => $streams[4],
  ...
  'includeDefectInstances' => 'true',
  'includeHistory' => 'true',
};

so I hope you can see that you will get the warning if you have an even number of elements in the array.

To fix things you need the value of the hash element to be an array reference, which is a scalar and won't upset the scheme of things

my $stream_defect_filter_spec = {
  'streamIdList' => \@streams,
  'includeDefectInstances' => 'true',
  'includeHistory' => 'true',
};

that way you can access the array elements as

$stream_defect_filter_spec->{streamIdList}[0]

etc.

And by the way you can tidy up your code substantially by letting map do what it's good at:

if (ref $x eq 'HASH') {
  push @streams, $x->{id};
}
elsif (ref $x eq 'ARRAY') {
  push @streams, map $_->{id}, @$x;
}
like image 97
Borodin Avatar answered Sep 29 '22 20:09

Borodin