-3

The code below works only with no strict. Can anyone suggest a better way to do it?

%hash5=('key5', 5);
my $hash_name = 'hash5';
print $$hash_name{'key5'}, "\n";

Again my aim: I do not know the hash name. I only know, it is store in the variable $hash_name. People have been suggesting things like:

 my $hashref = \%hashABC;

which requires me to know that the hash name is '%hashABC'. Using this example just above i would like to do sth like:

 my $hash_name = 'hashABC'; 
 my $hashref = \%$hash_name; # not possible, hope u get the aim

now i do not need to know the name of the hash anymore. That is what i want.

Thx a lot guys! (perl 5)

Sinan Ünür
  • 116,958
  • 15
  • 196
  • 339
user152037
  • 201
  • 2
  • 8
  • But, you needed to know the hash name when you did `my $hash_name = 'hash5';`. Once I setup a reference, I no longer need the actual hash name either. – David W. Apr 08 '14 at 15:59
  • 8
    See [Why it's stupid to use a variable as a variable name](http://perl.plover.com/varvarname.html). – ThisSuitIsBlackNot Apr 08 '14 at 16:20
  • See also http://stackoverflow.com/questions/3871451/in-perl-how-can-i-use-a-string-as-a-variable-name – Sinan Ünür Apr 08 '14 at 17:29
  • Where does the value of `$hash_name` come from? – Sinan Ünür Apr 08 '14 at 17:30
  • The thread: "How can I use a variable as a variable name in Perl? " does not answer my question either. Not to my understanding. – user152037 Apr 08 '14 at 18:19
  • To the text: "Why it's stupid to use a variable as a variable name". I understand the point but do not agree in my case. I could just create the most complex array and store everything inside, yes. But i want legibility and intuitivity in my code. So if i have an array of people-ages it must have the name %person_age, not %hash, where other thousend things are inside. And if i have one array for people/age, one for people/phonenumber, one for people/gender ... than i'd like to access them iteratively thru a variable. – user152037 Apr 08 '14 at 18:25
  • 5
    Sorry, but that approach is neither more legible nor more intuitive than the alternative, and is very likely to introduce difficult-to-find bugs. Use a hash of hashes or an array of hashes instead. For example, `my %people = ( bob => { age => 55, phone => '123-4567' }, fred => { age => 42, phone '345-6789' } );` To print all the phone numbers, do `foreach my $person (keys %people) { print $people{$person}{phone}, "\n"; }` – ThisSuitIsBlackNot Apr 08 '14 at 18:48
  • 3
    You can also use objects to encapsulate your data, allowing you to do something like: `foreach my $person (@people) { print $person->phone_number, "\n"; }` See [`perldoc perlootut`](http://perldoc.perl.org/perlootut.html). – ThisSuitIsBlackNot Apr 08 '14 at 18:50

3 Answers3

7

Instead of referring to the hash by name, use references.

# Here is our hash
my %hash = (key => 5);
# we make a reference to the hash
# this is like remembering the name of the variable, but safe
my $hashref = \%hash;

# here are two ways to access values in the referenced hash
say $$hashref{key};
say $hashref->{key}; # prefer this

Alternatively, keep a hash of hashes so that you can look up items by name:

# here is our hash again
my %hash = (key => 5);
# and here is a hash that maps names to hash references
my %hash_by_name;
# we remember the %hash as "hash5"
$hash_by_name{hash5} = \%hash;

# now we can access an element in that hash
say $hash_by_name{hash5}{key};

# we can also have a variable with the name:
my $name = "hash5";
say $hash_by_name{$name}{key};

Learn more about references in perlreftut.

amon
  • 57,091
  • 2
  • 89
  • 149
  • Hi, you are not realy accessing the hash thru a variable. In both cases you need to know that your hash is called 'hash'. Thus it does not answer my question, unfortunately. – user152037 Apr 08 '14 at 15:19
  • @user152037 I added a few comments to clarify what I'm doing. If that doesn't answer your question, I'm afraid I don't quite understand it – please edit your question to make it clearer. – amon Apr 08 '14 at 15:29
  • edited! Check above pls – user152037 Apr 08 '14 at 15:47
0

In this case, disable strict temporally looks like the best solution, you can do it like this

#!/usr/bin/perl

use strict;
use warnings;

our %hash5=('key5', 5);
my $hash_name = 'hash5';

my $hash_ref;

{
    no strict "refs";
    $hash_ref = \%$hash_name;
}

print $hash_ref->{key5}, "\n";

Note: For this to work, %hash5 must be a global variable.

Lee Duhem
  • 14,695
  • 3
  • 29
  • 47
  • Sorry. I could nt get the answer at perldoc perlref. It just repeats the solutions presented here and in related questions. But not exactly the solution to my question. Or is it me, who did not get it? :-) – user152037 Apr 08 '14 at 15:50
  • @user152037 Looks like disable `strict refs` temporally is the best you can get. – Lee Duhem Apr 08 '14 at 16:35
0

I don't know where the data in %hash_name come from. Did you read and store them in %hash_name? If so, perhaps a simpler solution would be to modify your program to read into a hash of hashes (as many have suggested), instead of reading into a global variable:

my %data = (
    hash_name => get_data(),
);
# and then ...
my $name = get_name(); # e.g., 'hash_name'
my $data = $data{ $name } or do {
    # error handling
    ...
};

Remember that the limitations that use strict imposes do not apply at all to the keys of a hash :-)

Edward
  • 486
  • 4
  • 14