in reply to Re^2: Avoiding circular references
in thread Avoiding circular references

Your problem can be solved using something similar to the aforementioned "trick", as shown below.

I've identified the three changes I've made using "# <-----".

use strict; use warnings; use Devel::Cycle; package A; sub new { my ( $class, $href ) = @_; my $self = { dbi => $$href{dbi} }; $self->{helper} = Helper->new( helper_function => sub { #$self->this_is_from_A(@_) shift->this_is_from_A(@_) # <----- }, ); bless $self, $class; } sub do_something { my $self = shift; #$self->{helper}->called_from_helper(); $self->{helper}->called_from_helper($self); # <----- } sub this_is_from_A { my ( $self, $arg ) = @_; print "$arg\nthis_is_from_A using $self->{dbi}\n"; } package Helper; sub new { my $class = shift; my %def = ( a => "something" ); my %arg = ( %def, ref $_[0] eq "HASH" ? %{ $_[0] } : @_ ); my $self = \%arg; bless $self, $class; } sub called_from_helper { my $self = shift; print "called_from_helper\n"; #$self->{helper_function}->("param from Helper"); $self->{helper_function}->(@_, "param from Helper"); # <----- } package main; my $a = A->new( { dbi => "some dbi object" } ); $a->do_something(); $a->do_something(); find_cycle($a);

Replies are listed 'Best First'.
Re^4: Avoiding circular references
by ikegami (Patriarch) on Dec 06, 2019 at 22:37 UTC

    In this case, however, it's easier to use weaken.

    Simply change

    sub new { my ( $class, $href ) = @_; my $self = { dbi => $$href{dbi} }; $self->{helper} = Helper->new( helper_function => sub { $self->this_is_from_A(@_) }, ); bless $self, $class; }
    to
    use Scalar::Util qw( weaken ); sub new { my ( $class, $href ) = @_; my $self = { dbi => $$href{dbi} }; { weaken( my $self = $self ); $self->{helper} = Helper->new( helper_function => sub { $self->this_is_from_A(@_) }, ); } bless $self, $class; }

    (By using the same name for the weakened variable as the unweakened one, we avoid using the wrong one by accident.)