An Intro to Moose

Chris Prather

Infinity Interactive

What Moose Is Not

What Moose Is

A Simple Example


package Person;
use strict;
use warnings;

sub new {
    my ($class) = @_;

    return bless {
        name => '',
        age  => undef,
    }, $class;
}

sub name {
    my ($self, $name) = @_;
    $self->{'name'} = $name if $name;
    return $self->{'name'};
}

sub age {
    my ($self, $age) = @_;
    $self->{'age'} = $age if $age;
    return $self->{'age'}; 
}

1;

A Simple Moose Example


package Person;
use Moose;

    has name => (is => 'rw');
    has age  => (is => 'rw');

1;

A Simple Moose Example (cont.)


package Person;
use Moose;

    has name => (is => 'rw');
    has age  => (is => 'rw');

1;

Variations on a Moose Example


package Person;
use Moose;

    has name => (
        is => 'rw', 
        isa => 'Str'
        default => 'Bob'
    );

    has age  => (
        is => 'rw',
        isa => 'Int',
        default => '0'
    );

1;

Variations on a Moose Example (cont.)


has name => (
    is => 'rw', 
    isa => 'Str'
    default => 'Bob'
);

            has 'date' => (isa => 'DateTime'); # This will DWIM

Variations on a Moose Example (cont.)


has name => (
    is => 'rw', 
    isa => 'Str'
    default => 'Bob'
);

has staff => (
    is => 'ro',
    isa => 'ArrayRef',
    default => sub { [qw(Bob Alice Tim)] },
);

Extending the Example


package Person;
use Moose;

    has name => (is => 'rw');
    has age  => (is => 'rw');


package Employee;
use Moose;
extends qw(Person);

    has manager =>  (
        is => 'ro',
        isa => 'Manager',
        required => 1, # Everybody has to have a manager
    );

package Manager;
use Moose;
extends qw(Employee);

    has staff => (
        is => 'rw',
        isa => 'ArrayRef',
        default => sub { [] },
    );

Extending the Example (cont.)


package Employee;
use Moose;
extends qw(Person);

    has manager =>  (
        is => 'ro',
        isa => 'Manager',
        required => 1, # Everybody has to have a manager
    );    

Some Type of Coercion


package Employee;
use Moose;
use Moose::Util::TypeConstraints;
extends qw(Person);

    subtype 'Manager' 
        => as 'Object'
        => where { $_[0]->isa('Manager') };

    coerce 'Manager' 
        => from 'Str'
        => via { Manager->new( name => $_) };

    has manager =>  (
        is => 'ro',
        isa => 'Manager',
        required => 1, 
        coerce => 1,
    );    

Some Type of Coercion (cont.)


    use Moose::Util::TypeConstraints;

subtype 'Manager' 
    => as 'Object'
    => where { $_[0]->isa('Manager') };
    
coerce 'Manager' 
    => from 'Str'
    => via { Manager->new( name => $_) };        

has manager =>  (
    ...
    coerce => 1,
);

Role of the Moose


package TeamMember;
use Moose;
extends qw(Employee);
with qw(ProjectTeamRole);

    has 'weekly_hours' => (
        is => 'ro',
        isa => 'Int',
        default => 40,
    );
1;

        $emp->does('ProjectTeamRole'); # true for TeamMembers

Role of the Moose (cont.)


package ProjectTeamRole;
use Moose::Role;

    requires qw('weekly_hours');

    has project => (
        is => 'ro',
        isa => 'Str',
        required => 1,
    )

    has project_hours => (
        is => 'rw',
        isa => 'Int',
        default => 0,
    )

    sub log_hours {
        my ($self, $hours) = @_;
        my $total = $self->project_hours + $hours;
        $self->project_hours($total);
    }
1;

Role of the Moose (cont.)


package ProjectTeamRole;
use Moose::Role;

    requires qw('weekly_hours');

Role of the Moose (cont.)


has project => (
   is => 'ro',
   isa => 'Str',
   required => 1,
)

has project_hours => (
   is => 'rw',
   isa => 'Int',
   default => 0,
)

sub log_hours {
    my ($self, $hours) = @_;
    my $total = $self->project_hours + $hours;
    $self->project_hours($total);
}

Role of the Moose (cont.)

Benefits of Moose

Drawbacks of Moose

Le Fin

And you for coming