paulw1128
paulw1128

Reputation: 464

Modifying hash slice gives inconsistent behavior

I have a set of buckets, and a set of 'removals' that potentially contains more/less buckets than the set I'm interested in - I am trying to subtract the removal values from the buckets with hash slices, like so:

@buckets{keys %buckets} -= @remove{keys %buckets};

However, it seems like only the LAST element of the hash ever gets modified - this is obviously inconsistent depending on the run-time order that the keys of the hash are returned.

Is this not a valid way to use hash slices?

Full Code:

use strict;
use warnings;
use Data::Dumper;

my %buckets = ( 
    a => 100,
    b => 200,
    c => 300,
    d => 400,
    );

my %remove = (
    a => 1,
    b => 2,
    c => 3,
    d => 4,
    ); 

my %before = %buckets;

@buckets{keys %buckets} -= @remove{keys %buckets};

# my @keys = keys %buckets;
# @buckets{@keys} -= @remove{@keys};  # Gives same behavior

warn Data::Dumper->Dump([ \%buckets ], ['buckets_after']);

Sample output:

% perl perltest.pl
$buckets_after = {
                   'd' => 400,
                   'c' => 300,
                   'a' => 100,
                   'b' => 198
                 };
% perl perltest.pl
$buckets_after = {
                   'c' => 300,
                   'd' => 400,
                   'b' => 200,
                   'a' => 99
                 };
% perl perltest.pl
$buckets_after = {
                   'a' => 100,
                   'd' => 400,
                   'b' => 200,
                   'c' => 297
                 };

Upvotes: 1

Views: 51

Answers (1)

user2404501
user2404501

Reputation:

Nothing specific to the hash slice operator here, it's just that the -= operator doesn't distribute over a list.

This doesn't work either, for the same reason:

($a,$b) = (10,20);
($a,$b) -= (1,1);
print "$a $b\n";

Write the loop explicitly to get what you want:

$buckets{$_} -= $remove{$_} for keys %buckets;

Upvotes: 3

Related Questions