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

I have 3 classes creating a hierarchy...

Foo
Bar
Baz

Foo is the top-most parent.

Each object has an accessor to it's possible child ($bar->baz), and a private accessor to its possible parent ($bar->_foo).

The parents and children are not compulsary, ie, to get a 'Bar' you don't need to automatically grab it's parent 'Foo' nor it's child 'Baz'.

The private accessors to their parents are obviously all weak-references.

Now here's the problem...

Within $bar->a_method() I need to get it's parent Foo object, so get one and store it in $bar->_foo for later possible use.

Obviously the moment I leave $bar->a_method, the parent Foo object has gone out of scope, and due to the weak-reference, I lose it in the parent accessor.

Turning off the weak reference in this case works for now, but in the future I may well have the Foo object created elsewhere, and also copied to the private parent accessor, so will need the weak-ref.

Any idea's of possible solutions?

(This is in Moose incase it makes any difference).

Replies are listed 'Best First'.
Re: weak-reference set internally
by Khen1950fx (Canon) on Sep 30, 2010 at 15:42 UTC
    You want to weaken $foo, $bar, and $baz; then you want to keep $foo as a weak reference while making $bar and $baz both a strong, normal reference again. That's the way I read it, so here's one way of doing it:
    #!/usr/bin/perl use strict; use warnings; use Scalar::Util qw(weaken isweak); use Scalar::Util::Refcount; my $foo; my $bar; my $baz; my $ref1 = \$foo; weaken($ref1); print my $weak = isweak($ref1), "\n"; print refcount($foo), "\n"; my $ref2 = \$bar; weaken($ref2); print $weak = isweak($ref2), "\n"; print refcount($baz), "\n"; my $ref3 = \$baz; weaken($ref3); print $weak = isweak($ref3), "\n"; print refcount($baz), "\n\n"; my $copy1 = $ref2; $weak = isweak($copy1); my $copy2 = $ref3; $weak = isweak($copy2), "\n";
    I used $copy to make $bar and $baz strong again; "isweak" from Scalar::Util to test if the refs were weak. If they're weak, they'll come back true. If they're not weak, they'll come back false; also, I checked the refcount with Scalar::Util::Refcount to double-check what was happening.

    Update: Fixed some omissions.

      Possibly, and thanks, will have to re-read in the morning when I'm more awake. I feel the isweak method may be the key.

      To illustrate the original problem, consider a literal parent, with a child, modelled as 2 classes.

      Obviously a parent can have a child, and the child can have that same parent, but that needs to be the weak reference.

      When I have a parent and get the child, i store it within the parent, at the same time giving the child a reference back to the parent.

      I now know I can always get to one from the other, and if they're not there, simply call a method to get them and store. hey presto, all fine and dandy.

      My issue is where I get a child (not needing the parent yet), and WITHIN one of its methods I need to check a property of the parent, i can get the parent fine, check it's property fine, but i feel i should keep a reference so i don't have to get it again later.

      Obviously since it's a weak reference from child to parent, it never stays in scope.

      Surely that's kinda easy to understand my thoughts, maybe I'm going about it all wrong, but that's how things are starting to be modelled in the system I'm refactoring.

Re: weak-reference set internally
by Anonymous Monk on Sep 30, 2010 at 08:35 UTC
    Within $bar->a_method() I need to get it's parent Foo object, so get one and store it in $bar->_foo for later possible use.

    Why? It sounds like a_method should not belong to the Bar class or Foo class, but your problem is very unclear.

      within $bar->a_method, i need to check a property of the parent, ie, in Foo.

      Hence the reason for getting the relevant Foo object, checking it, all good so far, but then want to also keep it for future use in case i need the parent again.

        but then want to also keep it for future use in case i need the parent again.

        So don't use weak references?