Search code examples
arraysperlperl-data-structures

Perl - anonymous hashmaps and arrays - few questions


Hello I am learning perl and I will post several assumptions here. So please feel free to commenting and correcting me if I am wrong somewhere.

  1. Creating hash are done (among several another ways) by:

    %numbers = qw(one 1 two 2);
    
  2. Creating array are done by following:

    @array = qw(one two);
    
  3. Above constructions represents "non anonymous" types. The main difference between non anonymous and anonymous types is that named types have a name which I can refer to. If I want to create anonymous types I need to change parenthesis () for square brackets [] in arrays, or for braces {} in hashes. Hash of hashes in other words are hash of references to other hashes. Thus I need to use {} in nested hash and not classic hash ().

    %HoH = (
        flintstones => {
            husband   => "fred",
            pal       => "barney",
        },
        jetsons => {
            husband   => "george",
            wife      => "jane",
            "his boy" => "elroy",  # quotes needed on key.
        },
        simpsons => {
            husband   => "homer",
            wife      => "marge",
            kid       => "bart",
        },
    );
    
  4. The same situation applies for multi dimensional arrays. Multi dimensional array is an array containing refernces to another array, thus [] needs to be used instead ().

    @array_of_arrays =  ( [ "one", "two", "three" ],
                          [  4,   5,  6,  7  ],
                          [ "alpha", "beta" ]
                        );
    
  5. If I had "non anonymous" hashes containing each family members (flinstones, jetsons, simpsons) which construction should I use for creating %HOH?

    $HOH{flinstones} = {%flinstones};
    

    or

    $HOH{flinstones} = \%flinstones;
    

    I am assuming that \%flinstones is simply assigning reference to $HOH{flinstones}, this means that whatever I do to %flinstones will influence the $HOH{flinstones} because it simply contains reference to it. On the other hand {%flinstones} is something like re-casting of "non anonymous" hash to "anonymous" hash. This has effect that %flinstones can be later modified or even deleted and it will not affect the $HOH{flinstones} because there is reference to anonymous hash.

  6. What will happen with variable in loop? When my $variable; is issued inside loop it overwrites old one or creates new, or it is the same variable, or what happens here?

    for($i=0;$i<4;$i++){
      my $variable=$i;
      print $variable
    }
    

Solution

  • I call them "literal hash", "literal array", but to each his own.

    You should know that in Perl--except in case of ties-- [...] and \@x are pretty much the same thing. And that {...} and \%h are as well. They both "construct" references to arrays and hashes.

    In question 5, both will do what you want. But one will do it more efficiently. Your second example stores the reference to an already defined hash as a value in another hash. The first example,

    $HOH{flinstones} = {%flinstones}
    

    creates a hash to return the address and expands %flintstones into a list, per the list context. Thus it stores a hash that is an exact copy of %flintstones in a separate hash that is stored in %HOH. You are correct that changes to %flintstones will not affect this copy.

    Here's a bit of advice for you. Install, Smart::Comments (SC), create some test scripts and just dump variable internals through STDERR. You'll be amazed at how much more you can learn seeing the internals of everything, you care to see.

    Here are some lessons from my experience with SC:

    • set $Data::Dumper::Maxdepth to some positive integer value if you're going to dump Win32::OLE objects, as each reference of the same OLE object may look like a different Perl object when traversed.

    • Never dump $_ by itself. For some reason the code in SC can change it. So always do something like this:

      my $a = $_;
      ### $_ : $a
      
    • IO handles don't dump, so don't try it. Use the default stringification.

    Now, finally, if you didn't dump %flintstones with %HOH, you would have no way of knowing--through a simple variable dump--whether the references were the same or not. However, remember that you can set $Data::Dumper::Maxdepth so that you won't get a complete dump. So you can test whether or not two references were the same by partially dumping them and using the straight generic Perl stringification of references.

    ### %flintstones : '' . \%flintstones 
    local $Data::Dumper::Maxdepth = 1;
    ### %HOH
    

    Seeing for yourself what the case is, is going to help you learn Perl faster than asking a raft of questions on Stackoverflow.