How can I return a whole hash map in Perl? - perl

I have a hash called
%values
Now I want to return the whole hash in a subroutine
sub getvalues {
return $values;
}
But then I got an error, because $value needs a definition and my program stops. If I'm using
sub getvalues {
return %values;
}
it seems to work, but my program is very slow and don't get further... So how can I return the whole map?

It would be nice to return the hash reference instead of hash,what you need to do is
First stote the hash into the hash ref then return it like
sub getvalues {
my %values = (test => "SO");
my $values = \%values;
return $values;
}

Related

Perl optimization: inlining a function changed the results

I profiled some code, and there is one function which stood out and I was wondering if there is a way to optimize it:
The function is defined as:
sub convert_arrayref {
if(ref($_[0]) eq 'ARRAY') {
return join(($_[1] || ","), #{$_[0]});
}
else {
return $_[0];
}
}
Most of the times the else block will get executed, and I was wondering if I could inline it rather than making a function call. The calling code looks as follows:
$data = convert_arrayref($data, '&')
So, what I did was change the calling code as:
if ($data eq 'ARRAY') {
$data = join('&', $data)
}
I thought this would be equivalent. However, the results are different. I am wondering if I have done something wrong here.
You get different results because you did not replicate the functionality of the if clause. You need to use ref to check if your variable is an array reference, and you need to deference the variable:
if (ref($data) eq 'ARRAY') {
$data = join('&', #{ $data })
}

Replace a variable as string with results from a subroutine in perl

I am trying to replace the variable "ex" with it's string value(which it gets from subroutine "potatoex()" and put it in the definition of another variable "goodge",
not getting any syntax error but this seems to be not working out.
Please help.
sub potatoex {
my $potato="Junos: 17.4DCB";
if($potato = ~/"Junos: 17.4[a-zA-Z0-9_.]*"/) {
print "/var/home/smoketest/dhcpv6.pl.28709.log";
}
}
main :
{
my $ex= potatoex();
my $goodge= "Apurva $ex Arnav";
print $goodge;
}
CURRENT O/P : /var/home/smoketest/dhcpv6.pl.28709.logApurva 1 Arnav
EXPECTED O/P: Apurva /var/home/smoketest/dhcpv6.pl.28709.log Arnav
Thanks,
Apurva
You are printing from your subroutine instead of returning the value from it. Try using return in potatoex.
sub potatoex {
my $potato = q{Junos: 17.4DCB};
my $returnVal = '';
if( $potato =~ /Junos: 17\.4[a-zA-Z0-9_.]*/ ) {
$returnVal = q{/var/home/smoketest/dhcpv6.pl.28709.log};
}
$returnVal;
}
{
my $ex = potatoex();
my $goodge = qq{Apurva $ex Arnav};
print $goodge;
}
While you could use return in an if block above (instead of print), I instead decided to use a variable, which will always return either the value you are trying to or an empty string. You could explicitly state the return return returnVal;, but it isn't required as perl allows implicit returns (make note of this and figure out if it should fit in your best practices or not).

perl cyclic reference. Is this what is happening

I am trying to write a daemon with perl. Now this daemon has the following code
sub b {
my $data;
if (some condition) {
$data->{"endsmeet"} = 1;
} else {
$data->{"endsmeet"} = 2;
}
my $newData = a($data);
}
sub a {
my ($data) = #_;
my %a = ();
my $newData = {
endsmeet => undef,
};
$a{"boo"} = $data->{"endsmeet"};
$newData->{"endsmeet"} = \%a;
return $newData;
}
My question is from the above, does the reference for %a go away and does it get cleaned up when b goes out of scope?
b returns the value of $newdata, which is a reference to an anon hash, which holds a reference to %a, which holds a scalar in the element with key boo.
If the value returned by b not stored, nothing will be referencing the value of $newdata, so it will get freed, so nothing will be referencing the anon hash, so it will get freed, so nothing will reference the scalar in the element with key boo, so it will get freed.
No cycles. No leak.

Array of hashes not being passed by ref to sub

I have a setter sub setAssignmentStatus which takes an array of hashes (AoH from here on) and another parameter (do not concern yourself with this as that part works), and does something iterating through the AoH to set another entry in each hash element. It does not return anything because I want to use the same AoH object with the added entries after it is pulled through the setter sub and not construct a whole new AoH and repopulate the entries. Here is the setter:
sub setAssignmentStatus
{
my $fileFlatArySclr = $_[0];
my $cfgFile = $_[1];
#here I convert the AoH from the scalar necessary for the sub to its native form
my #fileFlatAry = #$fileFlatArySclr;
#this works, don't worry
my %cfgVarHash = getConfigVars($cfgFile);
foreach my $fileVarHashSclr(#fileFlatAry)
{
#convert each AoH entry from scalar necessary for iteration to native hash
my %varHash = %$fileVarHashSclr;
my $varName = $varHash{'VAR_NAME'};
my $asgnLineCnt = $varHash{'ASGN_CNT'};
my $asgnSts;
my $fileAsgnSts;
my $cfgAsgnSts;
if($asgnLineCnt > 0) { $fileAsgnSts = 1; } else { $fileAsgnSts = 0; }
my $cfgAsgnLine = $cfgVarHash{$varName};
if($cfgAsgnLine ne undef) { $cfgAsgnSts = 1; } else { $cfgAsgnSts = 0; }
$asgnSts = $fileAsgnSts.$cfgAsgnSts;
#debug to make sure $asgnSts is not null in the first place (it is not!)
print "\n*** setting ASGN_STUS of ".$varName." to ".$asgnSts;
#Here we set ASGN_STUS for every iteration
$varHash{'ASGN_STUS'} = $asgnSts;
}
}
It is called as follows:
setAssignmentStatus(\#fileFlatAry, $cfgFile);
However, after sending the #fileFlatAry AoH through setAssignmentStatus, each element hash does not contain an ASGN_STUS entry. Why is that and how can I fix it?
My suspicion is that I am doing something wrong with the \ modifier, which is how I am getting the data structure to be passed as a scalar parameter to the sub but I am not sure.
You modify %varHash instead of modyfing the referenced hash. Stop copying everything into local variables and modyfying the local variables.
$varHash{'ASGN_STUS'} = ...;
should be
$fileVarHashSclr->{'ASGN_STUS'} = ...;
I wouldn't do my #fileFlatAry = #$fileFlatArySclr; either. Pure waste.

Perl: How to check what is being returned from a subroutine

I have a subroutine that will return two hashes when all goes well. But the sub checkouts output of command and if it matches a certain pattern, it returns with "-1". Is there anyway to check the return of the subroutine from where I called it?
Kinda like:
if (RETURN_VALUE == -1){
do something}
else
go as normal with the hashes
How could one function return two hashes?
If you mean hashrefs, the check would be quite simple:
my ($h1,$h2) = myFunction();
if ( !ref($h1) || (ref($h1) ne "HASH"))
{
die 'error';
}
You function should return references to the two hashes on success and nothing upon failure. Then you can just check the truth value of the function call.
sub myfunc {
my %hash1;
my %hash2;
return (\%hash1, \%hash2);
}
my $ref1;
my $ref2;
unless (($ref1, $ref2) = myfunc()) {
print "Something went wrong\n";
} else {
print "OK\n";
}
If you return two (or any number for that matter) hashes from a subroutine, the result will be a single hash. You will not be able to separate the original hashes from the result in a normal manner. Returning hash references will not exhibit this problem.
Suppose foo() returns two hash references when the pattern is matched and returns -1 when it does not match.
my ( $value_1, $value_2 ) = foo;
if ( $value_1 == -1 ) {
# pattern did not match
}
else { # for strict checks: elsif ( ref $value_1 eq 'HASH' && ref $value_2 eq 'HASH' ) {
# pattern matched
}