NOTE: This presentation is now out of date.
          Please see 
http://kablamo.org/slides-intro-to-moo
for the most up to date version.
          
use Moo;
          
          is equivalent to
use strict;                   # strict vars, refs, subs
use warnings FATAL => 'all';
no indirect;                  # can't do `my $alien = new Alien;`
no multidimensional;          # can't do `$hash{1,2}`
no bareword::filehandles;     # can't do `open FH, $filename`
use base 'Moo::Object';       # provides new(), etc
          
          also use Moo imports some methods: 
extends(), with(), has(), before(), around(), and after()
It inflates your Moo class to a Moose class
my $alien = Alien->new(@args)
new() calls Alien->BUILDARGS(@args)new() instantiates object, creating $selfnew() calls BUILD($self)new() returns $selfis called before instantiation
package Alien;
use Moo;
sub BUILDARGS {
    my ($class, @args) = @_;
   
    # -- modify @args here --
   
    return { @args };
}
          
          In Moose you need to call SUPER at the end
is called after instantiation
package Alien;
use Moo;
sub BUILD {
    my ($self, $args) = @_;
   
    # -- additional validation or logging here --
}
          
          The return value is ignored
new() to just create an object.is called when the object is destroyed
package Alien;
use Moo;
sub DEMOLISH {
    my ($self, $in_global_destruction) = @_;
   
    $self->dbh->disconnect;
}
          
        my $alien = Alien->new(@args)$alien->DESTROY()undef $alien$alien->DESTROY()$alien->DESTROY() calls $alien->DEMOLISH() at every level of inheritance
package Alien;
use Moo;
has eyes      => (is => 'rw');
has nostrils  => (is => 'ro');
          
          
my $alien = Alien->new( nostrils => 20 );
$alien->eyes(10);     # succeeds
$alien->nostrils(10); # dies
          
        ro attributesrw when you need that
package Alien;
use Moo;
has eyes     => (is => 'ro', default => sub { 5 });
has nostrils => (is => 'ro', builder => '_build_nostrils');
# Perlism: methods that start with _ are private
sub _build_nostrils { 5 }
          
        
has tentacles => (is => 'lazy');
          
          is equivalent to
has tentacles => (is => 'ro', lazy => 1, builder => '_build_tentacles');
          
        Use MooseX::AttributeShortcuts to get support for is => 'lazy' in Moose
is unpredictable
package Alien;
use Moo;
use Tentacle;
has tentacle_count => (is => 'ro', default => sub { 5 });
has tentacles      => (is => 'ro', builder => '_build_tentacles');
sub _build_tentacles { 
  my $self = shift;
  my @tentacles;
  push @tentacles, Tentacle->new() for (1..$self->tentacle_count);
  return \@tentacles;
}
          
        
package Alien;
use Moo;
use Tentacle;
has tentacles      => (is => 'lazy');
has tentacle_count => (is => 'ro', default => sub { 5 });
sub _build_tentacles { 
  my $self = shift;
  my @tentacles;
  push @tentacles, Tentacle->new() for (1..$self->tentacle_count);
  return \@tentacles;
}
          
        
use Scalar::Util qw/looks_like_number/;
has antenna => (
  is  => 'ro', 
  isa => sub { ref(shift) eq 'Antenna'},
);
has antenna_count => (
  is  => 'ro', 
  isa => sub { looks_like_number(shift) },
);
          
        
use MooX::Types::MooseLike qw/:all/;
has eyes => (is => 'ro', isa => Int);
          
        
use Types::URI -all;
has uri => (is => 'ro', isa => Uri);
use Types::Standard -all;
has is_from_mars => (is => 'ro', isa => Bool);
          
        
use Scalar::Util qw(looks_like_number);
use Type::Tiny;
 
my $NUM = "Type::Tiny"->new(
   name       => "Number",
   constraint => sub { looks_like_number($_) },
   message    => sub { "$_ ain't a number" },
); 
has eyes => (is => 'ro', isa => $NUM);
          
        Coercions are also a bit up in the air atm
Unlike Moose, coercions are separate from type checking
package Client;
use Moo;
use URI;
has uri => (is => 'ro', coerce => \&string_to_uri } );
sub string_to_uri {
  my $value = shift;
  return $value if ref $value eq 'URI'
  return URI->new($value);
}
          
          
my $client = Client->new( uri => 'http://example.com' );
$client->uri->host;  # returns example.com
          
        
package ConfigFile;
use Moo;
use Path::Class;
has _file => (
  is      => 'ro', 
  handles => [qw/spew slurp/],
  default => sub { Path::Class::file('.configuration') },
);
          
          
my $config_file = ConfigFile->new();
$config_file->slurp(); # read in file contents
          
        
package ConfigFile;
use Moo;
use Path::Class;
has _file => (
  is      => 'ro', 
  handles => { write => 'spew', read => 'slurp'},
  default => sub { Path::Class::file('.configuration') },
);
          
          
my $config_file = ConfigFile->new();
$config_file->read(); # slurp in file contents
          
        A code reference run after an attribute is set
has cowboy => (
  is      => 'ro', 
  trigger => sub { warn "cowboy attr set"; }
);
          
        
package Brontosaurus;
extends 'Dinosaur';
before eat => sub {
  my ($self, $food) = @_;
  die "bad params" if $food eq 'meat';
};
          
          Receives same params as the original method
Return value is ignored
Good for adding extra validation
package Brontosaurus;
extends 'Dinosaur';
after eat => sub {
  my ($self, $food) = @_;
  $self->log->warning("Brontosaurus does not like to eat $food")
    if $food eq 'meat';
};
          
          Receives same params as the original method
Return value is ignored
Good for logging/debugging
package Brontosaurus;
extends 'Dinosaur';
around eat => sub {
  my ($orig, $self, $food) = @_;
  uc $orig->($self, $food);
};
          
          Called instead of the original method
package Searchable;
use Moo::Role;
# state
has 'number_of_results' => (is => 'ro', default => sub { 5 }); 
# behavior
sub search { ... }
          
          
package Thing;
use Moo;
with qw/Searchable/;
          
          
my $thing = Thing->new();
$thing->search();
          
        
package Searchable;
use Moo::Role;
requires 'search_engine';
sub search { 
  my ($self, $query) = @_;
  my $json = $self->search_engine->search($query);
  return JSON->new->utf8->decode($json);
}
          
          
package Thing;
use Moo;
with qw/Searchable/;
sub search_engine {
  return Bing->new();
}
          
        
print "hi" if Thing->does('Searchable');