Unable to properly merge hashes - perl

I currently have the following
# $dog, $cat, $rat are all hash refs
my %rethash = ('success' => 'Your Cool');
my %ref ={ 'dog' => $dog, 'cat' => $cat, 'mouse' => $rat,
'chicken' => '' };
my $perlobj = ( \%ref,\%rethash );
When $perlobj is dumped this is the result
$VAR1 = {
'success' => 'Your Cool'
};
However when warnings are enabled I get the following message
Useless use of reference constructor in void context at ..
I realize there is something terribly wrong with how %ref is assigned using {}, What is wrong with this code? I can't seem to get rid of this warning....
EDIT:
Ok I think I figured out whats going on,
my $perlobj = ( \%ref,\%rethash );
This does not merge but results in $perlobj becoming a reference to %rethash, this is obvious after reading your responses.

What RobEarl is saying is correct. I'll give an explanation of that and add some more stuff.
Your variable name %ref and the fact that you are using {} kinda implies you want a reference here.
Let's take a look what value we will have in %ref. Consider this example.
use strict; use warnings;
use Data::Printer;
my %foo = { key => 'value' };
p %foo;
This will throw a warning Reference found where even-sized list expected on my Perl 5.20.2. The output will be:
{
HASH(0x7e33c0) undef
}
It's a hash with a hashref as the key and undef as a value. HASH(0x07e33c0) is what you get when you look at a hash reference without dereferencing it. (The {} are there because Data::Printer converts the hash to a hashref).
Back to your code, the correct sigil for a reference is $. It does not matter what kind of reference it is. The reference is always a scalar (a pointer to the place in memory where the hash/array/something) is stored.
my $ref = {
dog => $dog,
cat => $cat,
mouse => $rat,
chicken => '', # maybe this should be undef?
};
Now you've got a hashref with the values of $dog, $cat, $rat and an empty string.
Now you're assigning a variable named $perlobj, which implies it's an object. Instead you are assigning a scalar variable (the $ makes it a scalar) with a list. If you do that, Perl will only assign the right-most value to the variable.
my $foo = (1, 2, 3); # $foo will be 3 and there's a warning
You are assigning a list of two references. The first one is disregarded and only \$rethash gets assigned. That works because conveniently, $perlobj is a scalar, and references are also scalars. So now $perlobj is a reference of %rethash. That's why your Data::Dumper output looks like %rethash.
I'm not sure what you want to do, so I cannot really help you with that. I suggest you read up on some stuff.
perlreftut is useful to learn how references work
If you want to do Object Oriented Programming, check out Moose
It might also be useful to just go get a book to learn a bit more about basic Perl. Learning Perl by Randal L. Schwartz and Beginning Perl by Curtis Poe are both very good for that

You are taking a list of hash references and assigning them to a scalar
my $perlobj = ( \%ref, \%rethash ); # same as $perlobj = \%rethash
Instead you want to take a reference to a merger of hashes
my $perlobj = { %ref, %rethash };

Related

perl: print a string from a hash that contains a reference to it

Sorry if this is a bad title.
I have the following hash:
my %map = (
'key1', 'hello',
'key2', \'there'
);
print Dumper(\%map);
output:
$VAR1 = {
'key2' => \'there',
'key1' => 'hello'
};
I want to print out the value at 'key2'. Here's what I've tried:
print "$map{key2}" => SCALAR(0x2398b08)
print "$$map{key2}" =>
print "$map->{key2}" =>
my goal:
print [some magic thing] => there
I'm new to perl, so I'm not 100% clear yet on how references behave and how to dereference them. How do I get what I'm looking for?
$map{key2} returns the value of the desired element. The element is a reference to a string.[1] If you wish to print the string referenced by that reference, you need to dereference it.
say ${ $map{key2} };
References:
Mini-Tutorial: Dereferencing Syntax
References quick reference
perlref
perlreftut
perldsc
perllol
I doubt this is intentional! This surely indicates an error somewhere.
$map{key2} is a reference to a scalar value \'there', so you need to dereference it
Your $$map{key2} and $map->{key2} both treat $map as a reference to a hash, but it doesn't even exist so that is wrong
You must use braces to disambiguate the order of evaluation
${ $map{key2} }
is what you want. Or you can write it in two steps
my $val = $map{key2};
print $$val, "\n";
I like to add the following line to all my perl scripts:
use strict;
This will keep you out of trouble with the scope of your variables. It does require you to scope all your variables with at a minimum of "my".
The following will let you print the value (of the hash associated with "key2") directly,
without the intermediate step of copying it out to another variable first.
print ${$map{'key2'}}, "\n";

Does iterating over a hash reference require implicitly copying it in perl?

Lets say I have a large hash and I want to iterate over the contents of it contents. The standard idiom would be something like this:
while(($key, $value) = each(%{$hash_ref})){
///do something
}
However, if I understand my perl correctly this is actually doing two things. First the
%{$hash_ref}
is translating the ref into list context. Thus returning something like
(key1, value1, key2, value2, key3, value3 etc)
which will be stored in my stacks memory. Then the each method will run, eating the first two values in memory (key1 & value1) and returning them to my while loop to process.
If my understanding of this is right that means that I have effectively copied my entire hash into my stacks memory only to iterate over the new copy, which could be expensive for a large hash, due to the expense of iterating over the array twice, but also due to potential cache hits if both hashes can't be held in memory at once. It seems pretty inefficient. I'm wondering if this is what really happens, or if I'm either misunderstanding the actual behavior or the compiler optimizes away the inefficiency for me?
Follow up questions, assuming I am correct about the standard behavior.
Is there a syntax to avoid copying of the hash by iterating over it values in the original hash? If not for a hash is there one for the simpler array?
Does this mean that in the above example I could get inconsistent values between the copy of my hash and my actual hash if I modify the hash_ref content within my loop; resulting in $value having a different value then $hash_ref->($key)?
No, the syntax you quote does not create a copy.
This expression:
%{$hash_ref}
is exactly equivalent to:
%$hash_ref
and assuming the $hash_ref scalar variable does indeed contain a reference to a hash, then adding the % on the front is simply 'dereferencing' the reference - i.e. it resolves to a value that represents the underlying hash (the thing that $hash_ref was pointing to).
If you look at the documentation for the each function, you'll see that it expects a hash as an argument. Putting the % on the front is how you provide a hash when what you have is a hashref.
If you wrote your own subroutine and passed a hash to it like this:
my_sub(%$hash_ref);
then on some level you could say that the hash had been 'copied', since inside the subroutine the special #_ array would contain a list of all the key/value pairs from the hash. However even in that case, the elements of #_ are actually aliases for the keys and values. You'd only actually get a copy if you did something like: my #args = #_.
Perl's builtin each function is declared with the prototype '+' which effectively coerces a hash (or array) argument into a reference to the underlying data structure.
As an aside, starting with version 5.14, the each function can also take a reference to a hash. So instead of:
($key, $value) = each(%{$hash_ref})
You can simply say:
($key, $value) = each($hash_ref)
No copy is created by each (though you do copy the returned values into $key and $value through assignment). The hash itself is passed to each.
each is a little special. It supports the following syntaxes:
each HASH
each ARRAY
As you can see, it doesn't accept an arbitrary expression. (That would be each EXPR or each LIST). The reason for that is to allow each(%foo) to pass the hash %foo itself to each rather than evaluating it in list context. each can do that because it's an operator, and operators can have their own parsing rules. However, you can do something similar with the \% prototype.
use Data::Dumper;
sub f { print(Dumper(#_)); }
sub g(\%) { print(Dumper(#_)); } # Similar to each
my %h = (a=>1, b=>2);
f(%h); # Evaluates %h in list context.
print("\n");
g(%h); # Passes a reference to %h.
Output:
$VAR1 = 'a'; # 4 args, the keys and values of the hash
$VAR2 = 1;
$VAR3 = 'b';
$VAR4 = 2;
$VAR1 = { # 1 arg, a reference to the hash
'a' => 1,
'b' => 2
};
%{$h_ref} is the same as %h, so all of the above applies to %{$h_ref} too.
Note that the hash isn't copied even if it is flattened. The keys are "copied", but the values are returned directly.
use Data::Dumper;
my %h = (abc=>"def", ghi=>"jkl");
print(Dumper(\%h));
$_ = uc($_) for %h;
print(Dumper(\%h));
Output:
$VAR1 = {
'abc' => 'def',
'ghi' => 'jkl'
};
$VAR1 = {
'abc' => 'DEF',
'ghi' => 'JKL'
};
You can read more about this here.

Need help understanding portion of script (globs and references)

I was reviewing this question, esp the response from Mr Eric Strom, and had a question regarding a portion of the more "magical" element within. Please review the linked question for the context as I'm only trying to understand the inner portion of this block:
for (qw($SCALAR #ARRAY %HASH)) {
my ($sigil, $type) = /(.)(.+)/;
if (my $ref = *$glob{$type}) {
$vars{$sigil.$name} = /\$/ ? $$ref : $ref
}
}
So, it loops over three words, breaking each into two vars, $sigil and $type. The if {} block is what I am not understanding. I suspect the portion inside the ( .. ) is getting a symbolic reference to the content within $glob{$type}... there must be some "magic" (some esoteric element of the underlying mechanism that I don't yet understand) relied upon there to determine the type of the "pointed-to" data?
The next line is also partly baffling. Appears to me that we are assigning to the vars hash, but what is the rhs doing? We did not assign to $_ in the last operation ($ref was assigned), so what is being compared to in the /\$/ block? My guess is that, if we are dealing with a scalar (though I fail to discern how we are), we deref the $ref var and store it directly in the hash, otherwise, we store the reference.
So, just looking for a little tale of what is going on in these three lines. Many thanks!
You have hit upon one of the most arcane parts of the Perl language, and I can best explain by referring you to Symbol Tables and Typeglobs from brian d foy's excellent Mastering Perl. Note also that there are further references to the relevant sections of Perl's own documentation at the bottom of the page, the most relevant of which is Typeglobs and Filehandles in perldata.
Essentially, the way perl symbol tables work is that every package has a "stash" -- a "symbol table hash" -- whose name is the same as the package but with a pair of trailing semicolons. So the stash for the default package main is called %main::. If you run this simple program
perl -E"say for keys %main::"
you will see all the familiar built-in identifiers.
The values for the stash elements are references to typeglobs, which again are hashes but have keys that correspond to the different data types, SCALAR, ARRAY, HASH, CODE etc. and values that are references to the data item with that type and identifier.
Suppose you define a scalar variable $xx, or more fully, $main:xx
our $xx = 99;
Now the stash for the main package is %main::, and the typeglob for all data items with the identifier xx is referenced by $main::{xx} so, because the sigil for typeglobs is a star * in the same way that scalar identifiers have a dollar $, we can dereference this as *{$main::{xx}}. To get the reference to the scalar variable that has the identifier xx, this typeglob can be indexed with the SCALAR string, giving *{$main::{xx}}{SCALAR}. Once more, this is a reference to the variable we're after, so to collect its value it needs dereferencing once again, and if you write
say ${*{$main::{xx}}{SCALAR}};
then you will see 99.
That may look a little complex when written in a single statement, but it is fairly stratighforward when split up. The code in your question has the variable $glob set to a reference to a typeglob, which corresponds to this with respect to $main::xx
my $type = 'SCALAR';
my $glob = $main::{xx};
my $ref = *$glob{$type};
now if we say $ref we get SCALAR(0x1d12d94) or similar, which is a reference to $main::xx as before, and printing $$ref will show 99 as expected.
The subsequent assignment to #vars is straightforward Perl, and I don't think you should have any problem understanding that once you get the principle that a packages symbol table is a stash of typglobs, or really just a hash of hashes.
The elements of the iteration are strings. Since we don't have a lexical variable at the top of the loop, the element variable is $_. And it retains that value throughout the loop. Only one of those strings has a literal dollar sign, so we're telling the difference between '$SCALAR' and the other cases.
So what it is doing is getting 3 slots out of a package-level typeglob (sometimes shortened, with a little ambiguity to "glob"). *g{SCALAR}, *g{ARRAY} and *g{HASH}. The glob stores a hash and an array as a reference, so we simply store the reference into the hash. But, the glob stores a scalar as a reference to a scalar, and so needs to be dereferenced, to be stored as just a scalar.
So if you had a glob *a and in your package you had:
our $a = 'boo';
our #a = ( 1, 2, 3 );
our %a = ( One => 1, Two => 2 );
The resulting hash would be:
{ '$a' => 'boo'
, '%a' => { One => 1, Two => 2 }
, '#a' => [ 1, 2, 3 ]
};
Meanwhile the glob can be thought to look like this:
a =>
{ SCALAR => \'boo'
, ARRAY => [ 1, 2, 3 ]
, HASH => { One => 1, Two => 2 }
, CODE => undef
, IO => undef
, GLOB => undef
};
So to specifically answer your question.
if (my $ref = *$glob{$type}) {
$vars{$sigil.$name} = /\$/ ? $$ref : $ref
}
If a slot is not used it is undef. Thus $ref is assigned either a reference or undef, which evaluates to true as a reference and false as undef. So if we have a reference, then store the value of that glob slot into the hash, taking the reference stored in the hash, if it is a "container type" but taking the value if it is a scalar. And it is stored with the key $sigil . $name in the %vars hash.

perl: can a hash entry reference be used to delete from the hash?

Here's some perl pseudo code for what I'm asking:
my %x;
# initialize %x
my $ref = whateverSyntacticSugarIsNeeded( $x{this}{hash}{is}{deep} );
# ...
# make use of $ref multiple times
# ...
delete $ref; # ideally, this would delete $x{this}{hash}{is}{deep}
... where the idea is to avoid use of $x{this}{hash}{is}{deep} more than is absolutely necessary.
I'm fairly sure this isn't possible and the least uses possible is 2 (the initial ref/copy of the value, then to delete the key/value pair from %x). However, if I'm mistaken then feel free to correct me.
It's not clear what you want exactly. If
%x = ( very => { deep => { hash => { is => "here" } } } );
and you assign
$y = $x{very}{deep}{hash}{is}
then is's like writing
$y = 'here'
so you can't delete $y. You can, though,
$z = $x{very}{deep}{hash};
delete $z->{is};
The easiest thing is just to reference the hash one level up.
This is especially true if you give the variable a semantically appropriate name (something other than ref):
my %x;
# initialize %x
my $ref = $x{this}{hash}{is};
# ...
# make use of $ref multiple times
# ...
delete $ref->{deep};
Perl tracks whether or not a piece of memory is used by using a count to that piece of memory. If I did this:
my $ref->{this}->{is}->{a}->{deep} = "hash";
undef $ref; # Note I use "undef" and not "delete"
I free up all of that memory. All of the hash references and the actual scalar that those hash references point to. That's because I have no further way of accessing that memory.
If I do something a bit simpler:
my %hash = ( one => 1, two => 2, ref => { three => 3, four => 4 }, five => 5 );
Note that $hash{ref} is a reference to another hash. If I did this:
my $ref = $hash{ref};
I now have two variables that can access that piece of memory. Doing this:
delete $hash{ref};
does not free up that memory because $ref still points to it. However, that hash reference is no longer in my %hash hash.
If I didn't delete $hash{ref}, but did this:
$ref->{seven} = 7;
I have changed %hash because $ref and $hash{ref} point to the same piece of memory: That same hash reference. Doing this:
delete $hash{ref}->{four};
or
delete $ref->{four};
will both delete a particular entry in that hash reference.
We don't have to do something that complex either:
my %hash = ( one => 1, two => 2, three => 3 );
my $ref = \%hash; #Creating a reference to that hash
delete $ref->{three};
This will delete $hash{three} since both are pointing to the same hash in memory. However,
undef $ref;
will not undefine $hash too.
I hope this covers your question. As long as there's another way to refer to a memory location, it's not freed in Perl. However, if you point a reference to a data structure, manipulating that data structure through the reference will manipulate that data structure referenced through an array or hash variable.

Is %$var dereferencing a Perl hash?

I'm sending a subroutine a hash, and fetching it with my($arg_ref) = #_;
But what exactly is %$arg_ref? Is %$ dereferencing the hash?
$arg_ref is a scalar since it uses the $ sigil. Presumably, it holds a hash reference. So yes, %$arg_ref deferences that hash reference. Another way to write it is %{$arg_ref}. This makes the intent of the code a bit more clear, though more verbose.
To quote from perldata(1):
Scalar values are always named with '$', even when referring
to a scalar that is part of an array or a hash. The '$'
symbol works semantically like the English word "the" in
that it indicates a single value is expected.
$days # the simple scalar value "days"
$days[28] # the 29th element of array #days
$days{'Feb'} # the 'Feb' value from hash %days
$#days # the last index of array #days
So your example would be:
%$arg_ref # hash dereferenced from the value "arg_ref"
my($arg_ref) = #_; grabs the first item in the function's argument stack and places it in a local variable called $arg_ref. The caller is responsible for passing a hash reference. A more canonical way to write that is:
my $arg_ref = shift;
To create a hash reference you could start with a hash:
some_sub(\%hash);
Or you can create it with an anonymous hash reference:
some_sub({pi => 3.14, C => 4}); # Pi is a gross approximation.
Instead of dereferencing the entire hash like that, you can grab individual items with
$arg_ref->{key}
A good brief introduction to references (creating them and using them) in Perl is perldoc perfeftut. You can also read it online (or get it as a pdf). (It talks more about references in complex data structures than in terms of passing in and out of subroutines, but the syntax is the same.)
my %hash = ( fred => 'wilma',
barney => 'betty');
my $hashref = \%hash;
my $freds_wife = $hashref->{fred};
my %hash_copy = %$hash # or %{$hash} as noted above.
Soo, what's the point of the syntax flexibility? Let's try this:
my %flintstones = ( fred => { wife => 'wilma',
kids => ['pebbles'],
pets => ['dino'],
}
barney => { # etc ... }
);
Actually for deep data structures like this it's often more convenient to start with a ref:
my $flintstones = { fred => { wife => 'Wilma',
kids => ['Pebbles'],
pets => ['Dino'],
},
};
OK, so fred gets a new pet, 'Velociraptor'
push #{$flintstones->{fred}->{pets}}, 'Velociraptor';
How many pets does Fred have?
scalar # {flintstones->{fred}->{pets} }
Let's feed them ...
for my $pet ( # {flintstones->{fred}->{pets} } ) {
feed($pet)
}
and so on. The curly-bracket soup can look a bit daunting at first, but it becomes quite easy to deal with them in the end, so long as you're consistent in the way that you deal with them.
Since it's somewhat clear this construct is being used to provide a hash reference as a list of named arguments to a sub it should also be noted that this
sub foo {
my ($arg_ref) = #_;
# do something with $arg_ref->{keys}
}
may be overkill as opposed to just unpacking #_
sub bar {
my ($a, $b, $c) = #_;
return $c / ( $a * $b );
}
Depending on how complex the argument list is.