Passing a hash to a subroutine without changing it input

  • A+
Category:Languages

I'm trying to debug some strange behavior while handling with a hash in Perl. I'm passing a hash (not ref) to a subroutine and for some reason it updates it.

some_sub($a,%{$hash}); sub some_sub {     my ($a,%hash) = @_;     my @struct;     while (my ($dir, $data) = each %hash) {         foreach my $id (keys(%{$data})) {             my $entry = $data->{$id};             $entry->{id} = $id;             my $parent = $data->{$entry->{id}};             unless ($parent) {                 push @struct, $entry             } else {                 push @{$parent->{children}},$entry;             }         }     } } my %h= %{$hash}; print Dumper(/%h); 

The sub some_sub does change %hash but only for the inner scope, so it should not change the data of the outside %hash. Also, I pass the hash as a hash and not as a hash ref. I suspected the sub some_sub inserts memory addresses into the %hash, but I'm not sure.

How should I debug and solve this issue?

EDIT: I also tried to pass a hash ref to the subroutine and do a dereferencing of the hash ref into another hash while doing all of the operations on the new hash.

 


Every value in a hash is a scalar. If you have a nested hash, the inner hash is stored as a scalar - a hash reference. Therefore, when changing the nested structures, the changes happen in the referenced hash, which is referenced from the original hash, too.

#! /usr/bin/perl use warnings; use strict;  sub change {     my %hash2 = @_;     for my $key (keys %hash2) {         ++$_ for values $hash2{$key};     } }  my %hash = (a => {b => 12, c => 24}); change(%hash); use Data::Dumper; print Dumper /%hash; 

Output:

$VAR1 = {           'a' => {                    'b' => 13,                    'c' => 25                  }         }; 

The process of obtaining a structure that's similar as the original but contains different references is called cloning or deep copying. See Clone or dclone from Storable.

Comment

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: