Reputation: 23
I'm working on a project for myself and I've been having an issue with passing a hash to a subroutine. There's several subroutines actually but I tried to strip it down to the bare minimum. I realize that the %mdc is a global hash so I don't have to pass it around to all of the subroutines I have but I'd prefer it that way out of habit. While the below snippet does work it feels like it could be cleaner.
Anyway, the part that's got my thinking that there must be a better way are the lines:
%mdc_def = mysub(\%mdc);
%mdc = %$mdc_def;
It feels... klunky to me but I'm not finding a way to make those two lines be just one... something like (even though it's bad syntax):
%mdc = %mysub(\%mdc);
Then if I should have a mysub2 that would also need that hash I'd have to do the same two line shuffle in that subroutine as well. It just feels messy.
Here's the snippet that I'm working on:
use strict;
use warnings;
my %mdc = ();
my $mdc_def;
$mdc{abc} = 123;
$mdc{cde} = 234;
foreach (sort keys (%mdc)) { print "before $_ = $mdc{$_}\n"; }
$mdc_def = mysub(\%mdc);
%mdc = %$mdc_def;
foreach (sort keys (%mdc)) { print " after $_ = $mdc{$_}\n"; }
sub mysub {
my ($mdc_def) = @_;
my %m = %$mdc_def;
$m{def} = 345;
$m{efg} = 456;
return \%m;
}
Thanks in advance.
Upvotes: 2
Views: 136
Reputation: 385590
You could use the following:
sub mysub {
my ($mdc_def) = @_;
my %m = %$mdc_def;
$m{def} = 345;
$m{efg} = 456;
return \%m;
}
my %mdc = ( a=>1, b=>2 );
%mdc = %{ mysub(\%mdc) };
But that makes not one by two copies of hashes and all the scalars within. There's no reason for the global var to be a hash instead of scalar, which would avoid one of the instances of copying.
sub mysub {
my ($mdc_def) = @_;
my %m = %$mdc_def;
$m{def} = 345;
$m{efg} = 456;
return \%m;
}
my $mdc = { a=>1, b=>2 };
$mdc = mysub(\%mdc);
That leaves one instance of copying. That instance is needed if you don't want mysub
to modify the hash in-place, so the above code is fine.
The following a version that modidies the hash in-place, avoiding the second instance of copying (and allowing us to leave the global var as a hash).
sub mysub_inplace {
my ($mdc_def) = @_;
$mdc_def->{def} = 345;
$mdc_def->{efg} = 456;
}
my %mdc = ( a=>1, b=>2 );
mysub_inplace(\%mdc);
Upvotes: 5
Reputation: 10903
Try
%mdc = %{mysub(\%mdc)};
\%mdc
will pass reference to %mdc
hash as parameter to mysub
suroutinemysub
call as hash reference and convert it to hashYou may use subroutine prototype sub mysub (\%)
to call mysub with mysub(%mdc)
Simple working example/script:
#!/usr/bin/perl
# Original version constained prototypes for sub mysub -
# see ikegami comments below the answear
use strict;
use warnings;
sub mysub {
my( $hRef ) = (@_);
$hRef->{a} = 0;
$hRef->{c} = 3;
return $hRef;
}
my %mdc = ( a=>1, b=>2);
%mdc = %{mysub(\%mdc)};
print %mdc;
Upvotes: 1
Reputation: 6798
Do you possess an understanding what is $hash_ref = \%hash
and how to use it?
use strict;
use warnings;
use feature 'say';
my %mdc = ();
$mdc{abc} = 123;
$mdc{cde} = 234;
say '- Before ------------';
while( my($k,$v) = each %mdc ) {
say "$k => $v";
}
mysub(\%mdc);
say '- After -------------';
while( my($k,$v) = each %mdc ) {
say "$k => $v";
}
sub mysub {
my $mdc_ref = shift;
$mdc_ref->{def} = 345;
$mdc_ref->{efg} = 456;
}
Output
- Before ------------
cde => 234
abc => 123
- After -------------
def => 345
cde => 234
abc => 123
efg => 456
Upvotes: 0