Beefy Boxes and Bandwidth Generously Provided by pair Networks
Don't ask to ask, just ask
 
PerlMonks  

How to explicitly destroy an object so that all other references to it would become false?

by bdimych (Monk)
on Feb 21, 2008 at 09:52 UTC ( #669224=perlquestion: print w/replies, xml ) Need Help??

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

is it possible, something like this?
my $x = bless {}, "XXX"; my $y = $x; some_superundef $x; if (! $y) { print "hurrah!\n"; }
  • Comment on How to explicitly destroy an object so that all other references to it would become false?
  • Download Code

Replies are listed 'Best First'.
Re: How to explicitly destroy an object so that all other references to it would become false?
by moritz (Cardinal) on Feb 21, 2008 at 10:20 UTC
Re: How to explicitly destroy an object so that all other references to it would become false?
by stiller (Friar) on Feb 21, 2008 at 10:21 UTC
    I guess that is possible, you could for example use scalar::weaken, but I've never seen a place where that behavior would be desirable, do you have an example?

    Usually, one let scopes take care of this:

    use strict; use warnings; my $z = bless {}, "XXX"; my $w; { $w = \$z; } print "hurray!\n" if ! $w; print "still got \$z" if $z;

    But, it would be interesting to see a good use for the solution you are asking for.

    hth
    Edit: unintentionally my'ed $w inside the inner scope...

      I agree that the concept of "weak references" is undesirable. In C++, I use "borrower" objects of my own invention: whitepaper here.

      Basically, instead of breaking the smart pointer, or doing without, I use a different smart pointer, that uses without owning. It knows about lifetime management without participating in it.

      —John

        I have used weak refernces in one perl application I wrote some time ago, because the client insisted he would have circular references.

        In my opinion, this is almost always both undesirable and easily avoidable. There is a huge difference in beeing able to query (even efficiently) for related objects, and litter direct references all about and in both directions. Most you get out of going down that road is a huge pain trying to assess correctness.

        I'm familiar with the kind of c++ pointer design you mention, and in C++ you will sometimes need them, but most often I think one should be able to do without if one otherwise arrange things so that you tell your objects to act upon input, in stead of doing things to them directly.

        But, there is so many design considerations I have not participated in or fully understood, so I am interested in seeing cases where it might make sense.

Re: How to explicitly destroy an object so that all other references to it would become false?
by kyle (Abbot) on Feb 21, 2008 at 13:45 UTC

    Your question sounds similar to the one in Object Suicide. Maybe the discussion there would help.

Re: How to explicitly destroy an object so that all other references to it would become false?
by jettero (Monsignor) on Feb 21, 2008 at 11:35 UTC
    It's definitely possible, but it's not the most efficient thing in the whole wide world. The simple solution is to keep track of all your copies of the object so you can either implicitly drop them off a scope, or explicitly undef them. But it's definitely possible:
    use strict; use Devel::FindBlessedRefs qw(find_refs); my $x = bless {}, "test1"; my $y = bless {}, "test1"; my $z = $x; undef $_ for find_refs "yeah";

    -Paul

Re: How to explicitly destroy an object so that all other references to it would become false?
by sundialsvc4 (Abbot) on Feb 21, 2008 at 15:15 UTC

    My general objection to this idea is not that it cannot be done, but rather that it will introduce a “bolt out of the blue” effect into the system. An apparently-unrelated bit of code over there has a very draconian effect over here, and I might not know to look “there” to diagnose what appears to be a bug “here.” Bear in mind that the hardest thing about resolving any bug – by far – is finding it.

    So, if you have a phalanx of references to something, to anything at all, then this might suggest a weakness in your overall design. It is better, in my opinion, for there to be one and only one “custodian of” any Thing of Interest. If other objects must maintain temporal references to it, consider instead having them “ask the custodian to find it.” Or, if that isn't practical, consider setting up a notification method in the various objects that are designed to have a reference to this Thing, so that when you need to destroy this Thing you can call this method and thereby cause each object to set its own reference to undef; to cause them to break their link to this Thing.

    (n.b. Don't go perldocing for “notification method.” That's my colloquial term.)

    What advantage does that have? Well, instead of doing something “to” them, from somewhere-else totally unexpected, you instead cause each object to do what needs to be done upon themselves. It explicitly documents the fact that this link can be broken, and it explicitly creates a highly-visible point in the code ... for this object ... when-and-where it actually happens.

    Now, all of the code for “this object” is once again self-contained and self-explaining. When you look at the package which defines this object, you see all of the code that materially affects it. It's all right here.

Re: How to explicitly destroy an object so that all other references to it would become false?
by Anonymous Monk on Feb 21, 2008 at 11:32 UTC
    Or you could add a layer of indirection.

    my $x = bless {}, "XXX"; my $y = \$x; undef $x; if (! $$y) { print "hurrah!\n"; }
Re: How to explicitly destroy an object so that all other references to it would become false?
by bdimych (Monk) on Feb 21, 2008 at 12:30 UTC
    1)
    Many thanks!

    2)
    >do you have an example?

    package XXX; my %already_created_objects; sub new { my ($class, $X) = @_; if (!$already_created_objects{$X}) { $already_created_objects{$X} = bless {somekey => $X} $class; } $already_created_objects{$X} }
    somewhere inside the script
    ... $obj = new XXX($some_var_which_can_repeat); ... if ($some_conditions) { some_superundef $obj } ...

    Scalar::Util::weaken can do what I would like, but, as I've understood, it is required to mark as "weak" every reference to the object? Indirection layer seems more handy, may be...

      but, as I've understood, it is required to mark as "weak" every reference to the object?

      No, the typical use would be to have only %already_created_objects contain weak references. Then normal object life-time control would take place and when an object is no longer referenced other than in %already_created_objects, that object would be destroyed and the value in %already_created_objects would transform into undef.

      If there is some reason you want to destroy the object while there are still live references to it besides %already_created_objects, then you should give more information to justify that unusual requirement.

      - tye        

Re: How to explicitly destroy an object so that all other references to it would become false?
by Joost (Canon) on Feb 22, 2008 at 00:42 UTC
Re: How to explicitly destroy an object so that all other references to it would become false?
by John M. Dlugosz (Monsignor) on Feb 22, 2008 at 00:33 UTC
    Have an intermediate object that everyone points to. The intermediate points to the real object, and offers one place to redirect it or undef it that everyone respects.

Log In?
Username:
Password:

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

How do I use this? | Other CB clients
Other Users?
Others studying the Monastery: (1)
As of 2023-09-26 22:21 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found

    Notices?