Skip to content

Easy Anonymous Objects

September 16, 2009
tags:

On use Perl; the other day revdiablo asked whether there were Anonymous objects as easily as hashrefs? any where within Moose or sitting (hiding!) on CPAN.

Well the answers posted gave a yes for both Moose & CPAN.

Here is my twist on things using something already on CPAN which uses Moose and its Class::MOP foundations: MooseX::SingletonMethod.

With this we can easily create anonymous singleton objects like so:

{
    package Anonyject;
    use MooseX::SingletonMethod;
}

my @dingfirsts;
for my $line ( 1..10 ) {
    push @dingfirsts, Anonyject->new->add_singleton_methods(
        ding => sub { 'ding' x $line },
        dong => sub { 'dong' x $line },
        line => sub { $line },
    )
}

for (@dingfirsts) {
    say "First ", $_->ding, " on line ", $_->line;
}

We can show that each of these objects created have unique anonymous classes using Moose introspection:

for (@dingfirsts) {
    say $_->line, ': ', ( $_->meta->class_precedence_list )[0];
}

# outputs
# => 1: Class::MOP::Class::__ANON__::SERIAL::2
# => 2: Class::MOP::Class::__ANON__::SERIAL::3
# => 3: Class::MOP::Class::__ANON__::SERIAL::4
# => 4: Class::MOP::Class::__ANON__::SERIAL::5
# => 5: Class::MOP::Class::__ANON__::SERIAL::6
# => 6: Class::MOP::Class::__ANON__::SERIAL::7
# => 7: Class::MOP::Class::__ANON__::SERIAL::8
# => 8: Class::MOP::Class::__ANON__::SERIAL::9
# => 9: Class::MOP::Class::__ANON__::SERIAL::10
# => 10: Class::MOP::Class::__ANON__::SERIAL::11

The rest of the class chain upwards for each of these objects is:
Anonyject >> Class::MOP::Class::__ANON__::SERIAL::1 >> Moose::Object

So you can add methods or attributes to Anonyject class and they will be available to all the anonymous objects created.

NB. Class::MOP::Class::__ANON__::SERIAL::1 is where the MooseX::Singleton methods live.

So for more proof in the singleton pudding:

my $obj1 = Anonyject->new->add_singleton_methods(
    ding => sub { "wing" },
    dong => sub { "wong" },
    line => sub { 23_939 },
);

my $obj2 = Anonyject->new->add_singleton_methods(
    something => sub { "else" },
);

say $obj1->ding;      # Says "wing"
say $obj2->something; # Says "else"

say $obj1->something; # Should break and now does
say $obj1->broken;    # Breaks properly
say $obj2->dong;      # And also breaks properly

And all these objects are easily extensible:

# add dingdong just to $obj2 
$obj2->meta->add_method( dingdong => sub { 'dingdong!' } );
say $obj2->dingdong;   # "dingdong!"

# add bang to all anonymous Anonyject objects
Anonyject->meta->add_method( 
    bang => sub { 'bang ' . ( $_[0]->meta->class_precedence_list )[0] } 
);
say $obj1->bang;       # "bang Class::MOP::Class::__ANON__::SERIAL::12"
say $obj2->bang;       # "bang Class::MOP::Class::__ANON__::SERIAL::13"

/I3az/

4 Comments leave one →
  1. dami permalink
    September 16, 2009 8:04 pm

    Fine, but when these anonymous objects go out of scope, Perl will reclaim the memory for instances, but not for the classes (classes remain in the _ANON_ symbol table, together with references to the “singleton methods” that were defined in those classes). So abusing this technique, especially in long-lived processes, could yield to memory leaks.

  2. hdp permalink
    September 16, 2009 11:41 pm

    This might have been true at one point, but it’s not anymore. Anonymous classes can be GCed just fine; I created 10000 of them (one at a time) and my process’s memory usage didn’t go up. This is with 5.10.

  3. September 17, 2009 1:46 am

    The way it works is that each instance of the anon-class will hold on to a reference to the metaclass (for the anon-class). So the metaclass (and the package it points too) will stay around as long as there is an instance around that needs it. Once all the instances are gone, then there will no longer be any references to the metaclass and the metaclass (and associated package) can be garbage collected.

  4. September 17, 2009 10:27 am

    Morning guys… many thanks for all the comments thus far!

    So yes anon-classes do tidy up behind themselves. From Class::MOP::Class pod:

    “Anonymous classes are destroyed once the metaclass they are attached to goes out of scope, and will be removed from Perl’s internal symbol table.”

    However saying that I may have a bug MooseX::SingletonMethods because quick test here seems to suggest those anon classes hang around in the symbol table. I’ll write up some proper empirical tests at weekend to get to bottom of it.

    /I3az/

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.

%d bloggers like this: