http://qs1969.pair.com?node_id=492933

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

...where the blessed object is just an index that's autoincremented every time the constructor is called. Or possibly the object is a closure that returns that index so you really can't fiddle with it. What are the main objections?

Replies are listed 'Best First'.
Re: inside-out objects using arrays?
by borisz (Canon) on Sep 17, 2005 at 23:13 UTC
    Better use a hash, since you may delete objects. Take a look at Class::Std for some hints, if you really want these objects.
    Boris
      I was thinking the following, which would lead to undef array elements once $obj->DESTROY gets called. Still, I like it ;-)
      package Outside::In; use strict; use warnings; { my $obj_counter = 0; my @name; sub new { my $class = shift; my $instance_index = $obj_counter; my $self = sub { return $instance_index }; bless $self, $class; $obj_counter++; return $self; } sub name { my $self = shift; $name[$self->()] = shift if @_; return $name[$self->()]; } sub DESTROY { my $self = shift; delete $name[$self->()]; } } package main; my $obj1 = Outside::In->new; my $obj2 = Outside::In->new; $obj1->name('Bob'); $obj2->name('Fred'); print $obj1->name, "\n", $obj2->name, "\n"; print $obj1->();
        I was thinking the following, which would lead to undef array elements once $obj->DESTROY gets called. Still, I like it ;-)

        The point borisz was making is that with a solution like this  @name always increases in length as objects are created and deleted, which will lead to you running out of memory in the long term.

Re: inside-out objects using arrays?
by xdg (Monsignor) on Sep 18, 2005 at 04:36 UTC

    What are you trying to achieve with this approach? There are many ways to make "inside-out" objects. The core idea is just that the object (the blessed reference) either (a) contains or (b) is itself (via it's memory address) an index to some other data storage container. That storage container could be almost anything, and accessed in almost any way.

    One reason that inside-out objects are interesting people lately is that it's possible, even easy, to make the container a "private" lexical and have the accessor reach it via a closure. On the other hand, you can make the storage global and do some really wild aliasing, too. (See my Object::LocalVars if you want to bend your brain.) It all depends what you're trying to accomplish.

    I'm not sure what the array storage gets you over a hash -- maybe a bit of speed, but extra hassle dealing with reclaiming memory as other posters have noted. One downside to the array is that it's possible to manipulate the index inside the blessed reference and potentially peek into other objects. I think Conway talks about this in Object Oriented Perl.

    With a hash and "unique" indices, you avoid that problem. On the other hand, as I pointed out in 'Threads and fork and CLONE, oh my!', using a memory address as a unique index breaks under threads or a pseudo-fork on Win32 unless you use Perl 5.8 and go to some pains with CLONE and again sacrifice efficiency for book-keeping.

    I'm not convinced there's a "right" way to do inside-out objects. Until Perl 6 anyway. (/me grins)

    I'm currently experimenting in a couple ways. With lots of attributes, keeping each in a separate hash like how Class::Std does is costly for destruction. I've been speculating whether the right approach is to keep one hash keyed on the index (needed for CLONE anyway), and have the contents be a hash reference with the keys being the individual attributes. Then DESTROY only needs to clean up one reference in the master hash, and let Perl's garbage collection take care of the rest.

    On the more bent side, I'm considering that approach but using anonymous symbol table refs, so I can get that elegance in cleanup and still use the local aliasing trick in Object::LocalVars. (Why do I feel like I'm on the path to the Dark Side when I say that...)

    So... if you want to use arrays for your inside-out objects, you can -- but know why you're doing it and what that gains you and what you give up in doing so.

    -xdg

    Code written by xdg and posted on PerlMonks is public domain. It is provided as is with no warranties, express or implied, of any kind. Posted code may not have been tested. Use of posted code is at your own risk.

      What are you trying to achieve with this approach?

      I don't have any particular goal in mind, mostly experimentation. 6 months ago perl objects were something weird where you had to use $foo->bar('baz') in some people's modules. I didn't understand how it worked. Then I learned a bit more. Then I understood the blessed hashref approach. Now I'm trying to get creative, that's all.

        Cool. Experimentation is a good thing in my book. If you haven't picked up a copy of Object Oriented Perl, I do recommend it as a guide to your experimentation. It doesn't cover some of the newer ideas we're talking about here, but the fundamental concepts and thinking all apply. Also, you may find a wealth of useful ideas in the Perl Design Patterns book/wiki. Best of luck,

        -xdg

        Code written by xdg and posted on PerlMonks is public domain. It is provided as is with no warranties, express or implied, of any kind. Posted code may not have been tested. Use of posted code is at your own risk.

Re: inside-out objects using arrays?
by rvosa (Curate) on Sep 18, 2005 at 18:11 UTC
    I ran some benchmarks, which might be of interest. I compared the node object for http://search.cpan.org/~rvosa/Bio-Phylo-0.04/lib/Bio/Phylo/Trees/Node.pm (actually, for the next version, with a different namespace, but the guts are the same), which uses an anonymous hashref, to the one below: Result:
    Rate old new old 477555/s -- -34% new 723066/s 51% --
    The salient point is that:
    sub get_parent { return $_[0]->{'PARENT'}; }
    seems quite a bit slower than:
    sub get_parent { return $parent[${$_[0]}]; }
    I've heard that array look-ups are faster than hash look-ups, but I thought the difference was smaller than it is.
Re: inside-out objects using arrays?
by jdhedden (Deacon) on Nov 14, 2005 at 20:05 UTC
Re: inside-out objects using arrays?
by Perl Mouse (Chaplain) on Nov 15, 2005 at 09:25 UTC
    How would you do inheritance? Which class is in charge of keeping track of the index? What about objects going out of scope? It's possible to get large arrays without having many objects.
    Perl --((8:>*