Hi! Please consider following me on twitter: @hanekomu.

Benchmarking immutable Mouse

Dann has added benchmarks for immutable Mouse to App::Benchmark::Accessors; I've also updated the benchmarks page.

Tags: , .

Write a comment | Bookmark and Share

posted at: 13:14 | path: /moose | permalink | 0 comments | 0 trackbacks

Dissecting the Moose Part 5 - Accessor Generator Benchmarks Updated

The results of the accessor generator benchmarks generated by App::Benchmark::Accessors now have a permanent page. I will update the page from time to time as new versions of the accessor generators are released.

Tags: , .

Write a comment | Bookmark and Share

posted at: 21:12 | path: /moose | permalink | 0 comments | 0 trackbacks

Moose::Manual

The newest versions of Moose include Moose::Manual. The Changes file says:

    * Moose::Manual
      - This is a brand new, extensive manual for Moose. This aims to
        provide a complete introduction to all of Moose's
        features. This work was funded as part of the Moose docs grant
        from TPF. (Dave Rolsky)

Tags: .

Write a comment | Bookmark and Share

posted at: 13:44 | path: /moose | permalink | 0 comments | 0 trackbacks

Dissecting the Moose Part 4 - Benchmarking Accessor Generators - Accessors Only

Update: Now uses Mojo 0.8.

Update 2: Now includes accessors and Class::MethodMaker.

Update 3: Now includes Object::Tiny, Spiffy, Class::Spiffy and direct hash access.

The previous benchmark tested mainly object construction; this benchmark performs a million get/set-operations on the same object.

As before, the benchmark was run on a 2.16 GHz MacBook with 2 GB RAM, Mac OS X 10.5.5, perl 5.8.8 (not the most recent one, I know):

Here is the program:

#!/usr/bin/env perl

use warnings;
use strict;
use Benchmark qw(cmpthese timethese :hireswallclock);


package WithMoose;
use Moose;
has myattr => ( is => 'rw' );


package WithMooseImmutable;
use Moose;
has myattr => ( is => 'rw' );
__PACKAGE__->meta->make_immutable;


package WithMouse;
use Mouse;
has myattr => ( is => 'rw' );


package WithClassAccessor;
use base qw(Class::Accessor);
__PACKAGE__->mk_accessors(qw/myattr/);


package WithClassAccessorFast;
use base qw(Class::Accessor::Fast);
__PACKAGE__->mk_accessors(qw/myattr/);


package WithClassAccessorFastXS;
use base qw(Class::Accessor::Fast::XS);
__PACKAGE__->mk_accessors(qw/myattr/);


package WithClassAccessorComplex;
use base qw(Class::Accessor::Complex);
__PACKAGE__->mk_new->mk_scalar_accessors(qw/myattr/);


package WithClassAccessorConstructor;
use base qw(Class::Accessor::Constructor Class::Accessor::Complex);
__PACKAGE__->mk_constructor->mk_scalar_accessors(qw/myattr/);


package WithMojo;
use base qw(Mojo::Base);
__PACKAGE__->attr('myattr');


package WithClassMethodMaker;
use Class::MethodMaker
    [ scalar => [ qw/myattr/ ],
      new    => [ qw/-hash new/ ],
    ];


package WithAccessors;
use accessors qw(myattr);

sub new { bless {}, shift }


package WithObjectTiny;
use Object::Tiny qw/myattr/;
sub set_myattr { $_[0]->{myattr} = $_[1] }


package WithSpiffy;
use Spiffy -base;
field 'myattr';


package WithClassSpiffy;
use Class::Spiffy -base;
field 'myattr';


package main;


my $moose                      = WithMoose->new;
my $moose_immutable            = WithMooseImmutable->new;
my $mouse                      = WithMouse->new;
my $class_accessor             = WithClassAccessor->new;
my $class_accessor_fast        = WithClassAccessorFast->new;
my $class_accessor_fast_xs     = WithClassAccessorFastXS->new;
my $class_accessor_complex     = WithClassAccessorComplex->new;
my $class_accessor_constructor = WithClassAccessorConstructor->new;
my $mojo                       = WithMojo->new;
my $class_methodmaker          = WithClassMethodMaker->new;
my $accessors                  = WithAccessors->new;
my $object_tiny                = WithObjectTiny->new;
my $spiffy                     = WithSpiffy->new;
my $class_spiffy               = WithClassSpiffy->new;
my $direct_hash                = {};

cmpthese(timethese(1_000_000,{
    moose => sub {
        $moose->myattr(27);
        my $x = $moose->myattr;
    },
    moose_immutable => sub {
        $moose_immutable->myattr(27);
        my $x = $moose_immutable->myattr;
    },
    mouse => sub {
        $mouse->myattr(27);
        my $x = $mouse->myattr;
    },
    class_accessor => sub {
        $class_accessor->myattr(27);
        my $x = $class_accessor->myattr;
    },
    class_accessor_fast => sub {
        $class_accessor_fast->myattr(27);
        my $x = $class_accessor_fast->myattr;
    },
    class_accessor_fast_xs => sub {
        $class_accessor_fast_xs->myattr(27);
        my $x = $class_accessor_fast_xs->myattr;
    },
    class_accessor_complex => sub {
        $class_accessor_complex->myattr(27);
        my $x = $class_accessor_complex->myattr;
    },
    class_accessor_constructor => sub {
        $class_accessor_constructor->myattr(27);
        my $x = $class_accessor_constructor->myattr;
    },
    mojo => sub {
        $mojo->myattr(27);
        my $x = $mojo->myattr;
    },
    class_methodmaker => sub {
        $class_methodmaker->myattr(27);
        my $x = $class_methodmaker->myattr;
    },
    accessors => sub {
        $accessors->myattr(27);
        my $x = $accessors->myattr;
    },
    object_tiny => sub {
        $object_tiny->set_myattr(27);
        my $x = $object_tiny->myattr;
    },
    spiffy => sub {
        $spiffy->myattr(27);
        my $x = $spiffy->myattr;
    },
    class_spiffy => sub {
        $class_spiffy->myattr(27);
        my $x = $class_spiffy->myattr;
    },
    direct_hash => sub {
        $direct_hash->{myattr} = 27;
        my $x = $direct_hash->{myattr};
    },
}));

To be fair, I've manually added a setter method to the Object::Tiny test class since Object::Tiny accessors only read, don't write. Here are the results:

Benchmark: timing 1000000 iterations of accessors, class_accessor, class_accessor_complex, class_accessor_constructor, class_accessor_fast, class_accessor_fast_xs, class_methodmaker, class_spiffy, direct_hash, mojo, moose, moose_immutable, mouse, object_tiny, spiffy...
 accessors: 1.9521 wallclock secs ( 1.94 usr +  0.01 sys =  1.95 CPU) @ 512820.51/s (n=1000000)
class_accessor: 4.21379 wallclock secs ( 4.18 usr +  0.02 sys =  4.20 CPU) @ 238095.24/s (n=1000000)
class_accessor_complex: 2.01732 wallclock secs ( 2.01 usr +  0.00 sys =  2.01 CPU) @ 497512.44/s (n=1000000)
class_accessor_constructor: 2.04444 wallclock secs ( 2.02 usr +  0.01 sys =  2.03 CPU) @ 492610.84/s (n=1000000)
class_accessor_fast: 2.04194 wallclock secs ( 2.01 usr +  0.01 sys =  2.02 CPU) @ 495049.50/s (n=1000000)
class_accessor_fast_xs: 0.744577 wallclock secs ( 0.74 usr +  0.01 sys =  0.75 CPU) @ 1333333.33/s (n=1000000)
class_methodmaker: 1.89544 wallclock secs ( 1.87 usr +  0.01 sys =  1.88 CPU) @ 531914.89/s (n=1000000)
class_spiffy: 2.05287 wallclock secs ( 2.05 usr +  0.01 sys =  2.06 CPU) @ 485436.89/s (n=1000000)
direct_hash: 0.405416 wallclock secs ( 0.40 usr +  0.00 sys =  0.40 CPU) @ 2500000.00/s (n=1000000)
      mojo: 1.71519 wallclock secs ( 1.70 usr + -0.01 sys =  1.69 CPU) @ 591715.98/s (n=1000000)
     moose: 1.89365 wallclock secs ( 1.87 usr +  0.01 sys =  1.88 CPU) @ 531914.89/s (n=1000000)
moose_immutable: 2.026 wallclock secs ( 2.00 usr +  0.02 sys =  2.02 CPU) @ 495049.50/s (n=1000000)
     mouse: 2.60332 wallclock secs ( 2.49 usr +  0.01 sys =  2.50 CPU) @ 400000.00/s (n=1000000)
object_tiny: 1.56868 wallclock secs ( 1.55 usr +  0.01 sys =  1.56 CPU) @ 641025.64/s (n=1000000)
    spiffy: 2.23854 wallclock secs ( 2.21 usr +  0.01 sys =  2.22 CPU) @ 450450.45/s (n=1000000)
                                Rate class_accessor mouse spiffy class_spiffy class_accessor_constructor class_accessor_fast moose_immutable class_accessor_complex accessors class_methodmaker moose mojo object_tiny class_accessor_fast_xs direct_hash
class_accessor              238095/s             --  -40%   -47%         -51%                       -52%                -52%            -52%                   -52%      -54%              -55%  -55% -60%        -63%                   -82%        -90%
mouse                       400000/s            68%    --   -11%         -18%                       -19%                -19%            -19%                   -20%      -22%              -25%  -25% -32%        -38%                   -70%        -84%
spiffy                      450450/s            89%   13%     --          -7%                        -9%                 -9%             -9%                    -9%      -12%              -15%  -15% -24%        -30%                   -66%        -82%
class_spiffy                485437/s           104%   21%     8%           --                        -1%                 -2%             -2%                    -2%       -5%               -9%   -9% -18%        -24%                   -64%        -81%
class_accessor_constructor  492611/s           107%   23%     9%           1%                         --                 -0%             -0%                    -1%       -4%               -7%   -7% -17%        -23%                   -63%        -80%
class_accessor_fast         495050/s           108%   24%    10%           2%                         0%                  --             -0%                    -0%       -3%               -7%   -7% -16%        -23%                   -63%        -80%
moose_immutable             495050/s           108%   24%    10%           2%                         0%                  0%              --                    -0%       -3%               -7%   -7% -16%        -23%                   -63%        -80%
class_accessor_complex      497512/s           109%   24%    10%           2%                         1%                  0%              0%                     --       -3%               -6%   -6% -16%        -22%                   -63%        -80%
accessors                   512821/s           115%   28%    14%           6%                         4%                  4%              4%                     3%        --               -4%   -4% -13%        -20%                   -62%        -79%
class_methodmaker           531915/s           123%   33%    18%          10%                         8%                  7%              7%                     7%        4%                --   -0% -10%        -17%                   -60%        -79%
moose                       531915/s           123%   33%    18%          10%                         8%                  7%              7%                     7%        4%                0%    -- -10%        -17%                   -60%        -79%
mojo                        591716/s           149%   48%    31%          22%                        20%                 20%             20%                    19%       15%               11%   11%   --         -8%                   -56%        -76%
object_tiny                 641026/s           169%   60%    42%          32%                        30%                 29%             29%                    29%       25%               21%   21%   8%          --                   -52%        -74%
class_accessor_fast_xs     1333333/s           460%  233%   196%         175%                       171%                169%            169%                   168%      160%              151%  151% 125%        108%                     --        -47%
direct_hash                2500000/s           950%  525%   455%         415%                       407%                405%            405%                   402%      387%              370%  370% 322%        290%                    87%          --

Some points of note:

Tags: .

Write a comment | Bookmark and Share

posted at: 12:58 | path: /dev | permalink | 0 comments | 0 trackbacks

Dissecting the Moose Part 3 - Benchmarking Accessor Generators

Update: Now also includes Mojo.

Update 2: Now uses Mojo 0.8.

Update 3: Now includes Class::MethodMaker.

Update 4: Now includes Object::Tiny, Spiffy, Class::Spiffy and direct hash access.

I wrote a small benchmarking program to compare the speeds of various accessor generators. They don't do much, just create an object while setting an accessor, then reading that accessor again, all for 100,000 times.

Here is the program:

#!/usr/bin/env perl

use warnings;
use strict;
use Benchmark qw(cmpthese timethese :hireswallclock);


package WithMoose;
use Moose;
has myattr => ( is => 'rw' );


package WithMooseImmutable;
use Moose;
has myattr => ( is => 'rw' );
__PACKAGE__->meta->make_immutable;


package WithMouse;
use Mouse;
has myattr => ( is => 'rw' );


package WithClassAccessor;
use base qw(Class::Accessor);
__PACKAGE__->mk_accessors(qw/myattr/);


package WithClassAccessorFast;
use base qw(Class::Accessor::Fast);
__PACKAGE__->mk_accessors(qw/myattr/);


package WithClassAccessorFastXS;
use base qw(Class::Accessor::Fast::XS);
__PACKAGE__->mk_accessors(qw/myattr/);


package WithClassAccessorComplex;
use base qw(Class::Accessor::Complex);
__PACKAGE__->mk_new->mk_scalar_accessors(qw/myattr/);


package WithClassAccessorConstructor;
use base qw(Class::Accessor::Constructor Class::Accessor::Complex);
__PACKAGE__->mk_constructor->mk_scalar_accessors(qw/myattr/);


package WithMojo;
use base qw(Mojo::Base);
__PACKAGE__->attr('myattr');


package WithClassMethodMaker;
use Class::MethodMaker
    [ scalar => [ qw/myattr/ ],
      new    => [ qw/-hash new/ ],
    ];


package WithObjectTiny;
use Object::Tiny qw/myattr/;


package WithSpiffy;
use Spiffy -base;
field 'myattr';


package WithClassSpiffy;
use Class::Spiffy -base;
field 'myattr';


package main;


cmpthese(timethese(100_000,{
    moose => sub {
        my $obj = WithMoose->new(myattr => 27);
        my $x = $obj->myattr;
    },
    moose_immutable => sub {
        my $obj = WithMooseImmutable->new(myattr => 27);
        my $x = $obj->myattr;
    },
    mouse => sub {
        my $obj = WithMouse->new(myattr => 27);
        my $x = $obj->myattr;
    },
    class_accessor => sub {
        my $obj = WithClassAccessor->new({ myattr => 27 });
        my $x = $obj->myattr;
    },
    class_accessor_fast => sub {
        my $obj = WithClassAccessorFast->new({ myattr => 27 });
        my $x = $obj->myattr;
    },
    class_accessor_fast_xs => sub {
        my $obj = WithClassAccessorFastXS->new({ myattr => 27 });
        my $x = $obj->myattr;
    },
    class_accessor_complex => sub {
        my $obj = WithClassAccessorComplex->new(myattr => 27);
        my $x = $obj->myattr;
    },
    class_accessor_constructor => sub {
        my $obj = WithClassAccessorConstructor->new(myattr => 27);
        my $x = $obj->myattr;
    },
    mojo => sub {
        my $obj = WithMojo->new(myattr => 27);
        my $x = $obj->myattr;
    },
    class_methodmaker => sub {
        my $obj = WithClassMethodMaker->new(myattr => 27);
        my $x = $obj->myattr;
    },
    object_tiny => sub {
        my $obj = WithObjectTiny->new(myattr => 27);
        my $x = $obj->myattr;
    },
    spiffy => sub {
        my $obj = WithSpiffy->new(myattr => 27);
        my $x = $obj->myattr;
    },
    class_spiffy => sub {
        my $obj = WithClassSpiffy->new(myattr => 27);
        my $x = $obj->myattr;
    },
    direct_hash => sub {
        my $h = {};
        $h->{myattr} = 27;
        my $x = $h->{myattr};
    },
}));

And here are the results, on a 2.16 GHz MacBook with 2 GB RAM, Mac OS X 10.5.5, perl 5.8.8 (yes, it's not the newest one):

Benchmark: timing 100000 iterations of class_accessor, class_accessor_complex, class_accessor_constructor, class_accessor_fast, class_accessor_fast_xs, class_methodmaker, class_spiffy, direct_hash, mojo, moose, moose_immutable, mouse, object_tiny, spiffy...
class_accessor: 0.680644 wallclock secs ( 0.67 usr +  0.00 sys =  0.67 CPU) @ 149253.73/s (n=100000)
class_accessor_complex: 0.890903 wallclock secs ( 0.88 usr +  0.01 sys =  0.89 CPU) @ 112359.55/s (n=100000)
class_accessor_constructor: 1.99036 wallclock secs ( 1.96 usr +  0.01 sys =  1.97 CPU) @ 50761.42/s (n=100000)
class_accessor_fast: 0.561965 wallclock secs ( 0.54 usr +  0.00 sys =  0.54 CPU) @ 185185.19/s (n=100000)
class_accessor_fast_xs: 0.4521 wallclock secs ( 0.44 usr +  0.00 sys =  0.44 CPU) @ 227272.73/s (n=100000)
class_methodmaker: 1.51813 wallclock secs ( 1.48 usr +  0.01 sys =  1.49 CPU) @ 67114.09/s (n=100000)
class_spiffy: 0.620832 wallclock secs ( 0.60 usr +  0.01 sys =  0.61 CPU) @ 163934.43/s (n=100000)
direct_hash: 0.116149 wallclock secs ( 0.12 usr +  0.00 sys =  0.12 CPU) @ 833333.33/s (n=100000)
            (warning: too few iterations for a reliable count)
      mojo: 1.00943 wallclock secs ( 0.95 usr +  0.01 sys =  0.96 CPU) @ 104166.67/s (n=100000)
     moose: 11.4151 wallclock secs (10.87 usr +  0.09 sys = 10.96 CPU) @ 9124.09/s (n=100000)
moose_immutable: 0.899679 wallclock secs ( 0.87 usr +  0.01 sys =  0.88 CPU) @ 113636.36/s (n=100000)
     mouse: 5.28056 wallclock secs ( 5.05 usr +  0.05 sys =  5.10 CPU) @ 19607.84/s (n=100000)
object_tiny: 0.382038 wallclock secs ( 0.31 usr +  0.01 sys =  0.32 CPU) @ 312500.00/s (n=100000)
            (warning: too few iterations for a reliable count)
    spiffy: 0.620199 wallclock secs ( 0.60 usr +  0.01 sys =  0.61 CPU) @ 163934.43/s (n=100000)
                               Rate moose mouse class_accessor_constructor class_methodmaker mojo class_accessor_complex moose_immutable class_accessor class_spiffy spiffy class_accessor_fast class_accessor_fast_xs object_tiny direct_hash
moose                        9124/s    --  -53%                       -82%              -86% -91%                   -92%            -92%           -94%         -94%   -94%                -95%                   -96%        -97%        -99%
mouse                       19608/s  115%    --                       -61%              -71% -81%                   -83%            -83%           -87%         -88%   -88%                -89%                   -91%        -94%        -98%
class_accessor_constructor  50761/s  456%  159%                         --              -24% -51%                   -55%            -55%           -66%         -69%   -69%                -73%                   -78%        -84%        -94%
class_methodmaker           67114/s  636%  242%                        32%                -- -36%                   -40%            -41%           -55%         -59%   -59%                -64%                   -70%        -79%        -92%
mojo                       104167/s 1042%  431%                       105%               55%   --                    -7%             -8%           -30%         -36%   -36%                -44%                   -54%        -67%        -87%
class_accessor_complex     112360/s 1131%  473%                       121%               67%   8%                     --             -1%           -25%         -31%   -31%                -39%                   -51%        -64%        -87%
moose_immutable            113636/s 1145%  480%                       124%               69%   9%                     1%              --           -24%         -31%   -31%                -39%                   -50%        -64%        -86%
class_accessor             149254/s 1536%  661%                       194%              122%  43%                    33%             31%             --          -9%    -9%                -19%                   -34%        -52%        -82%
class_spiffy               163934/s 1697%  736%                       223%              144%  57%                    46%             44%            10%           --    -0%                -11%                   -28%        -48%        -80%
spiffy                     163934/s 1697%  736%                       223%              144%  57%                    46%             44%            10%           0%     --                -11%                   -28%        -48%        -80%
class_accessor_fast        185185/s 1930%  844%                       265%              176%  78%                    65%             63%            24%          13%    13%                  --                   -19%        -41%        -78%
class_accessor_fast_xs     227273/s 2391% 1059%                       348%              239% 118%                   102%            100%            52%          39%    39%                 23%                     --        -27%        -73%
object_tiny                312500/s 3325% 1494%                       516%              366% 200%                   178%            175%           109%          91%    91%                 69%                    38%          --        -62%
direct_hash                833333/s 9033% 4150%                      1542%             1142% 700%                   642%            633%           458%         408%   408%                350%                   267%        167%          --

Some points of note:

Tags: .

Write a comment | Bookmark and Share

posted at: 10:54 | path: /dev | permalink | 0 comments | 0 trackbacks

Dissecting the Moose

I have a few blog posts on Moose, in which I write about things I'm learning about Moose as I go along.

This page serves as an entry point into this list of posts.

Tags: .

Write a comment | Bookmark and Share

posted at: 11:37 | path: /articles | permalink | 0 comments | 0 trackbacks

Dissecting the Moose Part 2 - Pragmatic Goodness

The synopsis of Moose.pm has this innocent-looking line:

use Moose; # automatically turns on strict and warnings

Which begs the question: "How does that work?" In this blog post, I'll try to uncover some of the magic of Perl pragmata.

When you say:

use Moose;

according to perldoc -f use, that really means:

BEGIN { require Moose; Moose->import(LIST); }

But Moose does not have either an import() or an unimport() subroutine. What's going on?

When loaded, that is, during the require() call, Moose.pm runs this code:

Moose::Exporter->setup_import_methods(...)

Looking at the setup_import_methods() subroutine in Moose::Exporter, it goes a few levels deeper but eventually comes up with anonymous subroutines which it installs in the caller's namespace, that is, in the Moose namespace, as import() and unimport().

So now there is an import() subroutine that the use() code shown above can run.

This still doesn't explain why the strict and warnings pragmata are turned on for every package that says use Moose.

If we look at the import() subroutine, we find these two lines:

strict->import;
warnings->import;

Both pragmata, strict and warnings, have import() subroutines that effectively set a few bits in the magic variable $^H.

perldoc perlvar has a section on $^H that explains:

This variable contains compile-time hints for the Perl interpreter. At the end of compilation of a BLOCK the value of this variable is restored to the value when the interpreter started to compile the BLOCK.

When perl begins to parse any block construct that provides a lexical scope (e.g., eval body, required file, subroutine body, loop body, or conditional block), the existing value of $^H is saved, but its value is left unchanged. When the compilation of the block is completed, it regains the saved value. Between the points where its value is saved and restored, code that executes within BEGIN blocks is free to change the value of $^H.

Moose::Exporter explains that calling strict->import; warnings->import; in a module's import() subroutine works because these pragmata set $^H, which affects the current compilation, that is, the file that uses Moose.pm. Therefore Moose doesn't need to do anything special to make it affect the file that uses Moose rather than Moose itself, because Moose has already been compiled.

So now we've gotten to the core of things. Let's try our new knowledge in a simple test setup. Let's write a little test program:

#!/usr/bin/env perl
use Foo;
$x = 1;

Note that we don't turn on strict or warnings, and we don't declare the variable $x.

Foo.pm looks like this:

package Foo;

print "Loading Foo.pm\n";

1;

When we run the test program, it prints Foo's message, then exits without error.

It doesn't make any difference if we just use the pragmata within Foo.pm:

package Foo;

use strict;
use warnings;

print "Loading Foo.pm\n";

1;

Running the program of course still doesn't complain that $x is undeclared.

Now let's do what Moose does and have an import() subroutine that causes the pragmata to be turned on:

package Foo;

use strict;
use warnings;

sub import {
    strict->import;
    warnings->import;
}

print "Loading Foo.pm\n";

1;

Now we get the desired effect:

$ perl test.pl 
Loading Foo.pm
Global symbol "$x" requires explicit package name at test.pl line 5.
Execution of test.pl aborted due to compilation errors.

Tags: .

Write a comment | Bookmark and Share

posted at: 11:14 | path: /dev | permalink | 0 comments | 0 trackbacks

Dissecting the Moose Part 1

Jesse Vincent (obra) said on IRC: "Moose looks big and scary, but turns out to be a big kitten. It still has claws, but it mostly is content to sit around in the sun and let you stroke its chin. In return, it looks pretty and entertains you."

But now I want to look inside Moose. Moose is basically a set of layers above Class::MOP. There is the syntactic sugar for the end-user, and a set of custom meta-classes underneath. Moose never creates objects or methods directly; it uses the underlying meta-object protocol to do that. For now, just have a brief look at interacting with Class::MOP:

#!/usr/bin/env perl

use warnings;
use strict;
use Data::Semantic::Net::IPAddress::IPv4;
use Class::MOP;
use Data::Dumper;

my $o = Data::Semantic::Net::IPAddress::IPv4->new;
my $meta = Class::MOP::Class->initialize(ref $o);
my @parents = $meta->class_precedence_list;
warn Data::Dumper->Dump([\@parents, $meta], [qw/*parents meta/]);

So here we create some standard object normally, but then we put the class under the care of Class::MOP. Now we can introspect the class with MOP methods like class_precedence_list(), which gives us a list of all parent classes. We also dump the meta-object itself to see what's going on.

@parents = (
             'Data::Semantic::Net::IPAddress::IPv4',
             'Data::Semantic::Net::IPAddress',
             'Data::Semantic::Net',
             'Data::Semantic',
             'Class::Accessor::Complex',
             'Class::Accessor',
             'Class::Accessor::Installer'
           );
$meta = bless( {
                 'namespace' => \undef,
                 'version' => $meta->{'namespace'},
                 'superclasses' => $meta->{'namespace'},
                 'method_metaclass' => 'Class::MOP::Method',
                 'attribute_metaclass' => 'Class::MOP::Attribute',
                 'package' => 'Data::Semantic::Net::IPAddress::IPv4',
                 'instance_metaclass' => 'Class::MOP::Instance',
                 'methods' => {},
                 'authority' => $meta->{'namespace'},
                 'attributes' => {}
               }, 'Class::MOP::Class' );

Here we can see that if we ask Class::MOP to create an instance of the class it will use Class::MOP::Instance to do it; if we want to add or inspect an attribute, it will use Class::MOP::Attribute to do it. If we wanted to change the way Class::MOP interacts with our previously standard Perl class, we could tell the meta-object to use different meta-classes.

This was not intended to be a complete tutorial of any sort; I'm just writing down things I'm discovering along the way.

Tags: .

Write a comment | Bookmark and Share

posted at: 10:03 | path: /dev | permalink | 0 comments | 0 trackbacks

Google::Chart - mooooooooooooose!

Daisuke Maki (lestrrat) has offered to take over the development of Google::Chart. That's great because there has been some feedback that I neither had the time nor the right motivation to act on. He also moosified the distribution in a branch.

Tags: .

Write a comment | Bookmark and Share

posted at: 16:48 | path: /dev | permalink | 0 comments | 0 trackbacks

First Moosifications

After hearing nothingmuch's Moose talk at YAPC::Asia I've now switched two of my CPAN distributions to Moose: Games::Go::Coordinate and Games::Go::Rank

Mooooooooooooooose!

Tags: .

Write a comment | Bookmark and Share

posted at: 20:48 | path: /dev | permalink | 0 comments | 0 trackbacks