Note that circular references are not intrinsically bad, only when they become memory leaks are they bad. There are a couple of approaches to handling circular references:

Personally, I prefer weak references. In this case, if your object of type Helper will only exist during the lifetime of the object of type A, then the following is one approach where the Helper object is a "child" of the A object, and a weak reference works fine, because the anonymous sub isn't closing over $self. Weakening $self->{parent} in Helper is fine, because we know the parent object will exist for the entire lifetime of the Helper, and we want the helper to be destroyed when the parent is destroyed.

use strict; use warnings; use Devel::Cycle; package A; sub new { my ($class, $href) = @_; my $self = { dbi => $$href{dbi} }; $self->{helper_child} = Helper->new( parent => $self, helper_function => sub { my $parent = shift; $parent->this_is_in_A(@_); }, ); bless $self, $class; } sub do_something { my $self = shift; $self->{helper_child}->do_helper(); } sub this_is_in_A { my ($self, $arg) = @_; print "this_is_in_A, arg: $arg, dbi is $self->{dbi}\n"; } sub DESTROY { print shift."->DESTROY\n" } package Helper; use Scalar::Util qw/weaken/; sub new { my $class = shift; my $self = { @_ }; weaken( $self->{parent} ); bless $self, $class; } sub do_helper { my $self = shift; $self->{helper_function}->($self->{parent}, "param from Helper"); } sub DESTROY { print shift."->DESTROY\n" } package main; my $x = A->new( { dbi => "some dbi object" } ); $x->do_something(); $x->do_something(); find_cycle($x); print "undef'ing \$x\n"; $x = undef; print "End\n"; __END__ this_is_in_A, arg: param from Helper, dbi is some dbi object this_is_in_A, arg: param from Helper, dbi is some dbi object undef'ing $x A=HASH(0x55e36742fc88)->DESTROY Helper=HASH(0x55e36742fdc0)->DESTROY End

Update: Note that in sub do_helper, we could also have done $self->{helper_function}->($self, "param from Helper");, so that the helper_function is called as if it were a method on the Helper class.


In reply to Re: Avoiding circular references by haukex
in thread Avoiding circular references by frazap

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.