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

Hi Monks, I am facing a weird problem due to unexpected behaviour of Perl OO ( I'm talking about mine expectations :P ) Please have a look at this test script :
use strict; use Data::Dumper; $Data::Dumper::Sortkeys = 1; my $object = bless {}, "MyMain"; $object->{a} = bless {}, "A"; $object->{b} = bless {}, "B"; $object->{c} = bless {}, "C"; $object->{a}->{var1} = "Pratik"; $object->{a}->{var2} = bless {}, "A1"; $object->{a}->{var2}->{name} = "Hello"; $object->{b}->{var1} = $object->{a}->{var2}; $object->{c}->{var1} = $object->{a}->{var2}; print Dumper($object); # # Start the magic. # my $dummy = bless {}, "A1"; $dummy->{name} = "CamelNeedsWater"; $object->{a}->{var2} = $dummy; print Dumper($object);
It generates output as :
$VAR1 = bless( { 'a' => bless( { 'var1' => 'Pratik', 'var2' => bless( { 'name' => 'Hello' }, 'A1' ) }, 'A' ), 'b' => bless( { 'var1' => $VAR1->{'a'}{'var2'} }, 'B' ), 'c' => bless( { 'var1' => $VAR1->{'a'}{'var2'} }, 'C' ) }, 'MyMain' ); $VAR1 = bless( { 'a' => bless( { 'var1' => 'Pratik', 'var2' => bless( { 'name' => 'CamelNe +edsWater' }, 'A1' ) }, 'A' ), 'b' => bless( { 'var1' => bless( { 'name' => 'Hello' }, 'A1' ) }, 'B' ), 'c' => bless( { 'var1' => $VAR1->{'b'}{'var1'} }, 'C' ) }, 'MyMain' );


Problem here is, assignments are behaving like COW, where as I'd expect them to behave like reference.

In my code, when I do $object->{a}->{var2} = $dummy;, I'd want $object->{b}->{var1} & $object->{c}->{var1} to still point to $object->{a}->{var2}, instead of getting it's own copy of old values.

Any inputs or work arounds ?

Thanks.

Replies are listed 'Best First'.
Re: Unforseen OO conducts
by Roy Johnson (Monsignor) on Oct 06, 2005 at 13:08 UTC
    $object->{a}->{var2} is a reference. When you assign $object->{b}->{var1} = $object->{a}->{var2}; you are making the two references refer to the same thing. Then, when you do $object->{a}->{var2} = $dummy; you are making that one refer to something else.

    If you want ...b... to refer to ...a..., then you need to make it a reference:

    $object->{b}->{var1} = \$object->{a}->{var2};
    but then you will have to add a layer of scalar dereferencing when getting the values out. The key point here is that there's a difference between two references referring to the same thing, and one reference referring to another reference.

    What you really want is an alias, but you can't do that except on top-level, non-lexical variables.


    Caution: Contents may have been coded under pressure.
Re: Unforseen OO conducts
by Perl Mouse (Chaplain) on Oct 06, 2005 at 13:05 UTC
    The OO part in your topic is a red herring.

    It has nothing to do with OO. Or bless. Or hashes. Or even references.

    If you do this:

    $var2 = "foo"; $var1 = $var2; $var2 = "bar"; print $var1;
    Do you expect it to print "bar"? It won't, and shouldn't. If you replace in the above code $var2 with $object->{a}->{var2}, $var1 with $object->{b}->{var1}, "foo" with bless {}, "A1"; and "bar" with $dummy, you get what you are doing.

    If you want to get at the current value of a variable, store a reference to that value.

    $var2 = "foo"; $var1 = \$var2; $var2 = "bar"; print $$var1; # Prints "bar", not "foo".
    (Fixed typo pointed to by thor)
    Perl --((8:>*
      Do you expect it to print "bar"? It won't, and shouldn't.
      It does and it should. :) Perhaps you have a typo in your code and meant something else...

      thor

      Feel the white light, the light within
      Be your own disciple, fan the sparks of will
      For all of us waiting, your kingdom will come

        I first had the roles for $var1 and $var2 reversed, but changed them to match the use of {var1} and {var2} by the OP. But I forgot to update the variable used in the print statement.

        Thanks.

        Perl --((8:>*