Package: perl
Version: 5.24.1-3+deb9u5
Severity: normal

I was trying to make program below as simple as possible, but I don't 
understand where is the bug introduced. 

The task is to make a copy of hash such that keys in new hash are made only out 
of alphanumerics and underscores "_". Hashes are nested. 

Here is the program: 

        #!/usr/bin/perl 

        use Data::Dumper; 

        sub hash_is_okey { 
                ref $_[0] eq "HASH" or return 0;  

                # for my $k (keys %{$_[0]}) { 
                #       my $v = ${$_[0]}{$k}; 

                while (my ($k, $v) = each %{$_[0]}) { 
                        $k =~ /\A[_[:alnum:]]+\z/ or return 0; 
                        hash_ok_or_scalar($v) or return 0; 
                }
                return 1;
        }

        sub hash_ok_or_scalar { return hash_is_okey($_[0]) || ! ref $_[0]; }

        sub make_hash_with_good_keys { 
                my ($x) = $_[0]; 

                hash_ok_or_scalar($x) and return $x; 

                ref $x eq "HASH" or die; 

                # copy hash "%{$x}" to new hash "%h" but make names good 
                my %h; 
                for my $k (keys %$x) { 

                        # copy "$k" to "$n", then make good name of "$n"
                        my $n = $k =~ s/[^[:alnum:]]/_/gr; 

                        $h{$n} = make_hash_with_good_keys($$x{$k}); 
                } 
                return \%h; 
        }

        my $original = { "top_level" => { "level down" => 123 } }; 
        my $with_good_keys = make_hash_with_good_keys($original); 

        print Dumper($original, $with_good_keys); 


and here is the result: 

        $VAR1 = {
                  'top_level' => {
                                   'level down' => 123
                                 }
                };
        $VAR2 = {
                  'top_level' => $VAR1->{'top_level'}
                };

In program hash "$with_good_keys" is made by:
* initializing new hash "%h", and then asigning to that hash new value
   or 
* plugging reference if "subhash" has good keys. 

But the result is bad, because "VAR2" has bad key "level down" -- contains 
space. 


If I change this part of program: 

                # for my $k (keys %{$_[0]}) { 
                #       my $v = ${$_[0]}{$k}; 

                while (my ($k, $v) = each %{$_[0]}) { 

to look like this (uncomment "for...keys", comment "while...each"): 

                for my $k (keys %{$_[0]}) { 
                        my $v = ${$_[0]}{$k}; 

                # while (my ($k, $v) = each %{$_[0]}) { 

then result is: 

        $VAR1 = {
                  'top_level' => {
                                   'level down' => 123
                                 }
                };
        $VAR2 = {
                  'top_level' => {
                                   'level_down' => 123
                                 }
                };

Now "$VAR2" is a copy with names modified as expected. 

This is extremely strange, because I don't write to hash I am iterating over 
with "while...each". I tried to
resolve this myself for many hours, but I failed. 



-- System Information:
Debian Release: 9.11
  APT prefers oldstable-updates
  APT policy: (500, 'oldstable-updates'), (500, 'oldstable')
Architecture: amd64 (x86_64)

Kernel: Linux 4.9.0-9-amd64 (SMP w/4 CPU cores)
Locale: LANG=pl_PL.UTF-8, LC_CTYPE=pl_PL.UTF-8 (charmap=UTF-8), 
LANGUAGE=pl_PL.UTF-8 (charmap=UTF-8)
Shell: /bin/sh linked to /bin/dash
Init: systemd (via /run/systemd/system)

Versions of packages perl depends on:
ii  dpkg               1.18.25
ii  libperl5.24        5.24.1-3+deb9u5
ii  perl-base          5.24.1-3+deb9u5
ii  perl-modules-5.24  5.24.1-3+deb9u5

Versions of packages perl recommends:
ii  netbase  5.4
pn  rename   <none>

Versions of packages perl suggests:
pn  libterm-readline-gnu-perl | libterm-readline-perl-perl  <none>
pn  make                                                    <none>
pn  perl-doc                                                <none>

-- no debconf information

Reply via email to