Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Perl: Define hash with reference to the same hash, $this->{key}?

Tags:

perl

How would I create a hash like the follow:

my %hash = (key1=>"Something", key2=>$hash{key1} . "Else");

Can this not be done while when I declare the hash? So far, the only thing I came up with was:

my %hash = (key1=>"Something");
$hash{key2} = $hash{key1} . "Else";
like image 458
SJaguar13 Avatar asked Jan 27 '10 16:01

SJaguar13


People also ask

How do I reference a hash in Perl?

Similar to the array, Perl hash can also be referenced by placing the '\' character in front of the hash. The general form of referencing a hash is shown below. %author = ( 'name' => "Harsha", 'designation' => "Manager" ); $hash_ref = \%author; This can be de-referenced to access the values as shown below.

How do I get the key of a hash in Perl?

The list of all the keys from a hash is provided by the keys function, in the syntax: keys %hashname . The list of all the values from a hash is provided by the values function, in the syntax: values %hashname . Both the keys and values function return an array.

How do you check if a hash has a key Perl?

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.


2 Answers

Why not use an intermediate variable?

my $common_value = 'Something';
my %some_hash = ( k1 => $common_value, k2 => $common_value.'Else' );

Update

kemp asked why we need an intermediate variable. I can interpret this question it two ways, I'll endeavor to answer both interpretations.

  1. Why can't you do my %hash = ( k1 => 'foo', k2 => $hash{k1}.'bar' );?

    The right-hand side (rhs) of the expression is evaluated before the left-hand side (lhs). So, when the value for k2 is determine, no assigment to %hash has yet occurred. In fact, %hash has not even been created and entered into the scratch pad yet. (%hash is a lexical variable here, so it won't go into the symbol table.)

  2. Why use a variable rather than another method?

    Well, there are many ways to initialize a hash with values like this. I would use an intermediate variable if I had a small number of related keys to initialize.

    my $cv1 = sub_result() * 5;
    my $cv2 = "Number: $cv1";
    
    my %h = (
        k1 => $cv1,  
        k2 => $cv2,
        k3 => "Numero: $cv1",
        k4 => "Big $cv2",
        k5 => "Round $cv2",
        k6 => "Whole $cv2",
        k7 => "-$cv1",
    );
    

    However, if I had to build up many complicated values that depended on many different keys, I'd probably use a data driven approach to initialize the hash. The exact implementation would depend on details I don't have, but it might look something like this:

    use Scalar::Util qw(reftype);
    
    my @init = ( 
        [ key1 => $value                 ],
        [ key2 => \&make_a_value, 'key1' ],
        [ key3 => \&another_way,  'key2' ],
    );
    
    my %h; 
    for my $spec ( @init ) {
        my $key   = shift @$spec;
        my $value = shift @$spec;
        my @args  = @$spec;
    
        if( reftype $value eq reftype sub {} ) {
            $value = $value->( @h{ @args } );
        }
    
        $h{$key} = $value;
    }
    

    For any case where this question arrises, the choice as to what technique to use depends on many details that are special to that instance. So we are left with the necessity to make generic statements. Intermediate variables are one good way approach the OP's problem. Whether they should be used in his particular case, I can not say.

like image 130
daotoad Avatar answered Oct 10 '22 03:10

daotoad


It cannot be done for 2 reasons:

  1. At the time Perl processes key2 => $hash{key1}, it has not yet associated the memory allocated with key 1 with the hash name hash. In other words, $hash{key1} does not point to the correct place in memory until after key2 => $hash{key1} is already assigned.

  2. Previous reason didn't state the additional problem: you didn't yet place %hash into a symbol table by the time you process key2 => $hash{key1} (again the order of parsing/evaluation), so the compiler will barf if you use strict; as you always should. This one is easily fixable with declaring my %hash in prior statement, but #1 is not.

like image 44
DVK Avatar answered Oct 10 '22 03:10

DVK