phigment has asked for the wisdom of the Perl Monks concerning the following question:

Hail wise ones.

I am trying to populate a hash with a generated (%pohash = ($tmp);)string.

No matter what I try I keep getting following error:

"Odd number of elements in hash assignment at ./test.pl line 27 (#1)"

And the hash then only contains 2 key/values.

I have read many other posts and reviewed Hash, Hashref and quoting. I have even dusted off
the llama ("Learning Perl").I can kinda sorta see what is wrong, the assignment string is breaking
into $VAR1 and $VAR2, but I can not seem to solve the problem.

Thank you all in advance.

Code and Output Follows: #!/usr/bin/perl use strict; use warnings; use diagnostics; use Data::Dumper; use DBI; my $dbargs = {AutoCommit => 0,PrintError => 1}; my $dbc = DBI->connect("dbi:SQLite:dbname=da_db.db","","",$dbargs); # get the default po my $sth = $dbc->prepare('select * from der_pos where poid = '0'); $sth->execute; my $po = $sth->fetchrow_hashref; my $tmp = ''; # build a string and add some commas while ( my ($key, $value) = each(%$po)) { if ($tmp) { $tmp = $tmp . ' , ';} $tmp = $tmp . "$key => " . (($value) ? qq("$value") : q("a +")); } #print $tmp . "\n"; my %pohash = (); %hash = ($tmp); print Dumper(%pohash); Output Follows: Odd number of elements in hash assignment at ./test.pl line 25 (#1) (W misc) You specified an odd number of elements to initialize a h +ash, which is odd, because hashes come in key/value pairs. $VAR1 = 'Comments => "a" , InstallAddID => "a" , County => "a" , Ariba +ToID => "a" , AribaFromID => "a" , ProcessStatus => "a" , DeliverToAd +dID => "a" , HasBadPart => "a" , ShipToCode => "a" , AribaPO => "Defa +ult" , DeptidCode => "a" , OrderType => "a" , PODateProcessed => "201 +0-06-29 10:53:25" , PODate => "a" , ShippingNotes => "a" , Requisitio +nNum => "a" , Mode => "a" , StoreNumber => "a" , Replaced => "a" , Ta +rget => "all" , OrderNotes => "a" , ReqDeliveryDate => "2010-06-29 10 +:53:25" , Iteration => "a" , LineItemCount => "a" , POID => "a" , Jam +coPO => "a" , DebugData => "a" , POTotal => "a"'; $VAR2 = undef; Issuing rollback() due to DESTROY without explicit disconnect() of DBD +::SQLite::db handle dbname=/da_db.db.

Replies are listed 'Best First'.
Re: Hash assignment "odd" ness
by kennethk (Abbot) on Jun 29, 2010 at 19:24 UTC
    The offending line, as reported in your error, is %hash = ($tmp);. The left hand-side of that statement is a hash and the right-hand side is a list with one element $tmp. The issue you are having is that you are assembling a string and trying to assign that to the hash instead of just storing directly in the hash. You could get Perl to do what you are asking it to do with eval, but why do that when you could just assign the values in the first place? This smells of an XY Problem.
    while ( my ($key, $value) = each(%$po) ) { $hash{$key} = $value ? $value : "a"; }

      Thank you!

      "list" was my disconnect. I tried the direct assignment construct multiple times, before I tried building the string and, every time Dumper out put would look like:

      $VAR1 = 'Comments'; $VAR2 = ''; $VAR3 = 'InstallAddID'; $VAR4 = ''; . . .

      When what I was expecting was:

      Comments = ''; InstallAddID = '';

      So the "X" is "%hash = ($never_gonna_work)" and the "Y" is "Why doesn't Dumper read my mind."

      print Dumper(\$po); would have solved my problem.<\p>

      Thanks again for the clarity. And this now works.

      #!/usr/bin/perl use strict; use warnings; use diagnostics; use Data::Dumper; use DBI; my $dbargs = {AutoCommit => 0,PrintError => 1}; my $dbc = DBI->connect("dbi:SQLite:dbname=da_hrb.db","","",$dbargs); # get the default po my $sth = $dbc->prepare('select * from der_po where poid = 0'); $sth->execute; my $po = $sth->fetchrow_hashref; # corrected. thanks ikegami print Dumper($po);
        Dumper takes a list of scalars for input. If you want to dump a hash, you need to pass a reference to the hash.
        print Dumper(%hash); # Dumps the result of evaluating the hash. Meh. print Dumper(\%hash); # Dumps the ref and the referenced hash. Good.

        On the other hand, $po is a scalar. No need to pass a reference to it.

        print Dumper(\$po); # Why?? print Dumper($po); # Good.
Re: Hash assignment "odd" ness
by Corion (Patriarch) on Jun 29, 2010 at 19:30 UTC

    I guess line 25 is that line:

    %hash = ($tmp);

    And that line meshes quite well with the diagnostic you got, and the explanation. What is this line supposed to do?

Re: Hash assignment "odd" ness
by ssandv (Hermit) on Jun 29, 2010 at 19:35 UTC

    You seem not to grasp the difference between a list and a string. A string is a single scalar composed of zero or more characters, while a list is a collection of zero or more separate scalars. ($foo) is always going to have an odd number of elements because it contains exactly one scalar. Hash assignment doesn't take a string, it takes a list.

Re: Hash assignment "odd" ness
by Argel (Prior) on Jun 30, 2010 at 19:44 UTC
    You've probably seen examples of assigning to a hash that look like this:
    my %favs = ( syfy => 'Babylon 5', fantasy => 'Lord of the Rings', animated => 'Monsters vs. Aliens', anime => 'El Cazador de la Bruja', );
    That is exactly the same as:
    my %favs = ( 'syfy', 'Babylon 5', 'fantasy', 'Lord of the Rings', 'animated', 'Monsters vs. Aliens', 'anime', 'El Cazador de la Bruja', );
    Which is the same as:
    my %favs = ( 'syfy', 'Babylon 5', 'fantasy', 'Lord of the Rings','ani +mated', 'Monsters vs. Aliens', 'anime', 'El Cazador de la Bruja', );
    So => is the same as a comma!! The only difference is that with => the operand on the left can be a bareword (i.e. does not normally have to be quoted). So that hash assignment is really just a list. And since perl is looking for key/value pairs the number of elements in the list has the be an even number.

    Elda Taluta; Sarks Sark; Ark Arks