eval a reference to a my hash
cdarke
created: 2006-04-05 07:23:57
I am trying to write a generic 'set' method. A simplified fragment:
my %drink;
# other attribute hashes

sub set {
   my ($key, $attr, $value) = @_;

   my $hashref;
   eval "\$hashref = \\\%$attr";
   
   if ( !defined $hashref ) {
      carp 'Invalid attribute name';
   }
   else {
      $hashref->{$key} = $value;
   }
}
The call to this subroutine:
set('larry', 'drink', 'Old Speckled Hen');
This does not work, i.e. it does not actually alter the 'real' hash (%drink). I have discover two fixes, but I cannot explain why either works 1. If I stringify the actual hash (%drink). After the assignment, if I add:
print "$drink{$key}\n";
it works. It seems to 'commit' $hashref. Using Data::Dumper or Devel::Peek::Dump also fixes it. 2. If I make the hash an 'our' variable it works. I'm setting warnings and use strict. Tried on 5.8.6 on Fedora and 5.8.7 on Windows. What is going on?
Re: eval a reference to a my hash
created: 2006-04-05 08:13:44

I don't understand why this doesn't work, but I do have a suggestion about how to fix it. Instead of using seperate hashes with different names, have a hash of hashrefs. Then you don't need an eval STRING or symbolic references to make it work.


Warning: Unless otherwise stated, code is untested. Do not use without understanding. Code is posted in the hopes it is useful, but without warranty. All copyrights are relinquished into the public domain unless otherwise stated. I am not an angel. I am capable of error, and err on a fairly regular basis. If I made a mistake, please let me know (such as by replying to this node).

Re^2: eval a reference to a my hash
created: 2006-04-05 08:37:51
Nice solution, I wanted to get rid of the eval anyway. Thanks!
I would still love to know why the original doesn't work.
Re^3: eval a reference to a my hash
created: 2006-04-05 13:48:32

By the time the eval STRING code runs, lexicals don't really have names anymore, so Perl can't look them up by name.

Re^4: eval a reference to a my hash
created: 2006-04-07 06:13:24
And that explains why making them our variables fixes the problem. Many thanks (I'm using an extra hash now and got rid of the eval, but it is worth knowing).
Cheers
Re^3: eval a reference to a my hash
created: 2006-04-05 14:00:27
When you say the original doesn't work, what makes you think it isn't?

It seems your simplified fragment is not demonstrating the problem, because:

#!/usr/bin/perl -w
                                                                                
# Strict
use strict;
use warnings;
                                                                                
# Libraries
use Carp;
use Data::Dumper;
                                                                                
                                                                                
my %drink;
# other attribute hashes
                                                                                
set('larry', 'drink', 'Old Speckled Hen');
print $drink{'larry'}, "\n";
# print "Dump(\%drink) => [%s]\n", Dumper(\%drink);
                                                                                
                                                                                
sub set {
   my ($key, $attr, $value) = @_;
                                                                                
   my $hashref;
   eval "\$hashref = \\\%$attr";
                                                                                
   if ( !defined $hashref ) {
      carp 'Invalid attribute name';
   }
   else {
      $hashref->{$key} = $value;
   }
}
is working for me:
% prog541345.pl
Old Speckled Hen
If that isn't what you're getting, please compare the above code fragment (based on what you provided in your post) to your actual code, and see if that helps locate the problem.

s''(q.S:$/9=(T1';s;(..)(..);$..=substr+crypt($1,$2),2,3;eg;print$..$/
Re^4: eval a reference to a my hash
created: 2006-04-07 06:10:26
It works because of the print statement. Take that out and it will fail. Thanks anyway.

perlmonks.org content © perlmonks.org and cdarke, chromatic, liverpole, theorbtwo

prlmnks.org © 2006 edmund von der burg (eccles & toad)

v 0.03