Beefy Boxes and Bandwidth Generously Provided by pair Networks
Problems? Is your data what you think it is?
 
PerlMonks  

Changing a variable which is a value of a hash

by benedicth (Initiate)
on Apr 16, 2015 at 15:40 UTC ( [id://1123628]=perlquestion: print w/replies, xml ) Need Help??

benedicth has asked for the wisdom of the Perl Monks concerning the following question:

Suppose there is a variable which is then declared a value of a hash. I then want to change $test to the content of $change but not change the hash reference. The result should be $test = 'change' while $hash{t} stays $test.
$test = 'test'; %hash = ( t => $test); $change = 'changed'; $hash{t} = $change; #I just want to change $test to 'changed' not $hash{t} to $change
I understand this is wrong but can't find an explanation for using variables as hash values. thanks for your help pros.

Replies are listed 'Best First'.
Re: Changing a variable which is a value of a hash
by choroba (Cardinal) on Apr 16, 2015 at 15:46 UTC
    Store the reference in the hash, not the value.
    #!/usr/bin/perl use warnings; use strict; my $test = 'test'; my %hash = ( t => \$test); # Store the reference. print join "\t", 'Before', ${ $hash{t} }, $test, $hash{t}, "\n"; my $change = 'changed'; ${ $hash{t} } = $change; # Change the value. print join "\t", 'After', ${ $hash{t} }, $test, $hash{t}, "\n"; __END__ Output: Before test test SCALAR(0x600078238) After changed changed SCALAR(0x600078238)
    لսႽ† ᥲᥒ⚪⟊Ⴙᘓᖇ Ꮅᘓᖇ⎱ Ⴙᥲ𝇋ƙᘓᖇ

      From the OP: "#I just want to change $test to 'changed' not $hash{t} to $change"

      From that i believe that OP wants the output like so:

      _END__ Output: Before test test ... After test changed ...

      Which is boggling to me ...

      UPDATE: ... so i implemented it using tied hashes:

      #!/usr/bin/env perl package MagicHash; require Tie::Hash; our @ISA = qw(Tie::Hash); sub TIEHASH { bless {}, shift } sub STORE { my ($self, $key, $newval) = @_; $self->{$key} = {key=>$key, value=>[$newval,$$newval]}; } sub FIRSTKEY { my ($self) = @_; keys %{$self}; my $first_key = each %{$self}; return undef unless defined $first_key; return $self->{$first_key}->{key}; } sub FETCH { my ($self, $key) = @_; my ($is_ref) = $key =~ s/^\\//; return $is_ref ? $self->{$key}->{value}->[0] : $self->{$key}->{value}->[1] ; } sub NEXTKEY { my ($self, $nextkey) = @_; my $next_key = each %{$self}; return undef unless defined $next_key; return $self->{$next_key}->{key}; } package main; use strict; use warnings; use Data::Dumper; { my $test = 'test'; my $changed = 'changed'; my %hash = ( t => \$test ); print "Before: \$test = $test\n", Dumper \%hash; ${ $hash{t} } = 'changed'; print " After: \$test = $test\n", Dumper \%hash; } { my $test = 'test'; my $changed = 'changed'; tie my %hash, 'MagicHash'; %hash = ( t => \$test ); print "Tied Before: \$test = $test\n", Dumper \%hash; ${ $hash{'\t'} } = 'changed'; print "Tied After1: \$test = $test\n", Dumper \%hash; ${ $hash{'\t'} } = 'again'; print "Tied After2: \$test = $test\n", Dumper \%hash; $hash{'t'} = \'one more'; print "Tied After3: \$test = $test\n", Dumper \%hash; }
      The trick is to store the value of the var and the reference to it in an anonymous array reference and then use some identifier (i chose the backslash) to distinguish which one is needed at the time. Very silly stuff. Sorry 'bout that. :)

      jeffa

      L-LL-L--L-LL-L--L-LL-L--
      -R--R-RR-R--R-RR-R--R-RR
      B--B--B--B--B--B--B--B--
      H---H---H---H---H---H---
      (the triplet paradiddle with high-hat)
      
        I tried to implement my solution with tying, too. The difference to your solution is there's no need to indicate what value you want: Perl just does what you mean, as usually:
        #!/usr/bin/perl use warnings; use strict; { package MagicScalar; use Tie::Scalar; use parent qw( -norequire Tie::StdScalar ); use overload nomethod => \&stringify; sub TIESCALAR { my $class = shift; bless [], $class } sub STORE { my ($self, $value) = @_; $self->[0] = $value; } sub FETCH { my $self = shift; return $self } sub stringify { my $self = shift; return $self->[0] } } { package MagicHash; use Tie::Hash; use parent qw( -norequire Tie::StdHash ); sub STORE { my ($self, $key, $value) = @_; my $previous = $self->{$key}; if (ref $previous and $previous->isa('MagicScalar')) { $previous->STORE($value); } else { $self->{$key} = $value } } } tie my $test, 'MagicScalar'; $test = 'test'; tie my %hash, 'MagicHash'; %hash = (t => $test); print "Before $hash{t} $test\n"; my $change = 'changed'; $hash{t} = $change; print "After $hash{t} $test\n";
        لսႽ† ᥲᥒ⚪⟊Ⴙᘓᖇ Ꮅᘓᖇ⎱ Ⴙᥲ𝇋ƙᘓᖇ
      Thank you!
Re: Changing a variable which is a value of a hash
by Your Mother (Archbishop) on Apr 16, 2015 at 15:56 UTC
Re: Changing a variable which is a value of a hash
by Laurent_R (Canon) on Apr 16, 2015 at 17:35 UTC
    Your question is not very clear to me, but, contrary to others who suggested to use references, I understand that you do NOT want the content of the hash to change when you change some variables in the environment. If you do this:
    $test = 'test'; %hash = ( t => $test); $test = 'changed';
    the content of the hash does not change, it is still 'test', because the assignment:
    %hash = ( t => $test);
    is storing into the hash the content of the $test variable at the time this assignment is done. Modifying the $test variable afterwards will not modify the content of the hash.

    But if you do:

    $change = 'changed'; $hash{t} = $change;
    then, of course the value in the hash will be modified because that's precisely a common way to modify the content of a hash for a given key.

    Je suis Charlie.
Re: Changing a variable which is a value of a hash
by GotToBTru (Prior) on Apr 16, 2015 at 15:48 UTC

    Use a reference:

    $test = 'test'; printf "Was: %s\n",$test; $hash{t} = \$test; $change = 'changed'; ${$hash{t}} = $change; printf "Now: %s\n",$test;
    Dum Spiro Spero
      thanks!
A reply falls below the community's threshold of quality. You may see it by logging in.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://1123628]
Approved by GotToBTru
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others meditating upon the Monastery: (6)
As of 2024-04-23 20:36 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found