SlideShare ist ein Scribd-Unternehmen logo
1 von 129
Introduction to Moose
        Italian Perl Workshop 2009
  Mike Whitaker - BBC / EnlightenedPerl.org
About me
About me

• BBC iPlayer team
About me

• BBC iPlayer team
• ex-Yahoo Europe (News team)
About me

• BBC iPlayer team
• ex-Yahoo Europe (News team)
• ex-CricInfo.com
About me

• BBC iPlayer team
• ex-Yahoo Europe (News team)
• ex-CricInfo.com
• Board member of EnlightenedPerl.org
Why Moose?
Why Moose?


• For that, we need a bit of history:
In the Beginning...
In the Beginning...
• ...there was Perl 5
In the Beginning...
• ...there was Perl 5
• DIY OO
In the Beginning...
• ...there was Perl 5
• DIY OO
•   perldoc perltoot
In the Beginning...
• ...there was Perl 5
• DIY OO
•   perldoc perltoot


      package Foo;

      sub new {
        my $self = {};
        return bless $self;
      }
In the Beginning...
                              package Foo;

•   ...there was Perl 5       sub new {
                                my $self = {};

• DIY OO                      }
                                return bless $self;


•   perldoc perltoot          sub bar {
                                my $self = shift;
                                my $val = shift;
      package Foo;              if (defined $val) {
                                    $self->{bar} = $val;
      sub new {                 }
        my $self = {};          else {
        return bless $self;         return $self->{bar};
      }                         }
                              }
Perl 5 Native OO
Perl 5 Native OO

• A bit of a hack
Perl 5 Native OO

• A bit of a hack
• Not really a first-class part of the language
Perl 5 Native OO

• A bit of a hack
• Not really a first-class part of the language
• Have to roll your own
So...
People started writing classes to make it
                easier....
Class::Accessor::Classy         Class::Accessor
Object::InsideOut         fields
                                  Hash::FieldHash
       Badger::Class Rubyish
  OP                                    Object::Declare
           Class::Maker UR         Class::Gomor
 Object::Tiny::XS Class::XSAccessor
                                         Class::Framework
       Class::Accessor::Fast Class::Simple
 Rose::Object MOP::MOP                         Coat
    Object::InsideOut         Class::STD
                                          Class::Object
   Class::Base     Class::ArrayObjects
                                                 Spiffy
     Class::Accessor::Grouped Class::Frame
 Object::Accessor Object::Tiny           Object::Simple
Class::Generate       Class::Builder   accessors
     Fukurama::Class                      Class::Define
                     Abstract::Meta::Class
Moose
What is Moose?
What is Moose?
• (Post)modern Perl OO framework
What is Moose?
• (Post)modern Perl OO framework
• Deals with the overhead of implementing
  OO, allows you to get on with coding
What is Moose?
• (Post)modern Perl OO framework
• Deals with the overhead of implementing
  OO, allows you to get on with coding
• Meta-object implementation - allows you to
  introspect your classes and objects
What is Moose?
• (Post)modern Perl OO framework
• Deals with the overhead of implementing
  OO, allows you to get on with coding
• Meta-object implementation - allows you to
  introspect your classes and objects
• Already used in production software
My First Class
package Person;
use Moose;

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

no Moose;
Using the class
use Person;
my $person = Person->new();

$person->name('Mike');

print $person->name();
> Mike
Adding a method
package Person;
use Moose;

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

sub introduce {
    print "I'm " . $self->name;
}
Using it
use Person;
my $person = Person->new();

$person->name('Mike');

$person->introduce();
> I'm Mike
Read-only attributes
package Person;
use Moose;

has name => ( is => 'ro' );

sub introduce {
    print "I'm " . $self->name;
}
Read-only attributes (2)

use Person;
my $person = Person->new();

$person->name('Mike');
# boom!
Read-only attributes (3)

use Person;
my $person = Person->new(
    { name => 'Mike' },
);

# no boom today!
Changing defaults
has 'name' => (
    isa => 'Str',
    reader => 'get_name',
    writer => 'set_name',
    init_arg => 'name',
    required => 1,
);
Types
package Person;
use Moose;

has name => (
    is => 'rw',
    isa => 'Str',
);
Types (2)
use Person;
my $person = Person->new();

$person->name('Mike');
# shiny!

$person->name( [] );
# boom!
# Not a Str
Types (3)
package Person;
use Moose;

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

has dob => (
    is => 'rw',
    isa => 'DateTime',
);
Types (4)
use Person;
my $person = Person->new(
   { name => 'Mike' }
);
my $dob = DateTime->new (
   year => 1963, month => 8, day => 5,
);
$person->dob($dob);
print $person->dob->year;
> 1963
Subclassing
package Student;
use Moose;
extends qw/Person/;

has overdraft => (
    isa => 'Bool',
    is => 'rw',
);
Compound Types
package Student;
use Moose;
extends qw/Person/;

has classes => (
    isa => 'HashRef[Str]',
    is => 'rw',
);
Required attributes
package Student;
use Moose;
extends qw/Person/;
# ...
has course => (
    isa => 'Str',
    is => 'ro',
    required => 1,
);
Setting defaults
package Student;
use Moose;

has 'overdraft' => (
    isa => 'Bool',
    default => 1,
);
But, what if...

package BankAccount;

sub balance {
    # yadda yadda
}
And then...
package Student;
use Moose;
extends qw/Person/;

has 'account' => (
    isa => 'BankAccount',
    is => 'rw',
    required => 1,
);
Lazy default
has 'overdraft' => (
    isa => 'Bool',
    is => 'ro',
    lazy => 1,
    default => sub {
      shift->account->balance < 0;
    }
);
Lazy builder
has 'overdraft' => (
    isa => 'Bool',
    is => 'ro',
    lazy_build => 1,
    init_arg => undef,
);
sub _build_overdraft {
   return shift->account->balance < 0;
}
Method modifiers
package Student;
# yadda yadda

after 'introduce' => sub {
    my $self = shift;
    print ', studying ' . $self->course;
}
Using it
use Student;
my $person = Student->new(
    name => 'Mike',
    course => 'Computer Science',
);

$person->introduce();
> I'm Mike, studying Computer Science
Method modifiers (2)
package Student;
# yadda yadda

around 'introduce' => sub {
    my ($next, $self, @args) = @_;
    print "Hi, ";
    $self->$next(@args);
    print ', studying ' . $self->course;
}
Using around
use Student;
my $person = Student->new(
    name => 'Mike',
    course => 'Computer Science',
);

$person->introduce();
> Hi, I'm Mike, studying Computer Science
Roles
Roles
• Code fragments that define and provide a
  small, reusable behaviour
Roles
• Code fragments that define and provide a
  small, reusable behaviour
• Not inherited - methods become part of
  consuming class
Roles
• Code fragments that define and provide a
  small, reusable behaviour
• Not inherited - methods become part of
  consuming class
 • can be overriden by comsuming class
Roles
• Code fragments that define and provide a
  small, reusable behaviour
• Not inherited - methods become part of
  consuming class
 • can be overriden by comsuming class
 • like MI but better!
Example role
package Age;
use Moose::Role;
has dob => (
    isa => 'DateTime', is =>'ro'
);
sub age {
    return DateTime->now
     ->subtract( shift->dob() )
     ->years;
}
Using a role
package Person;
use Moose;
with qw/Age/;
has name => ( isa => 'Str', is => 'ro');

sub introduce {
    print "I'm " . $self->name .
       ', age ' . $self->age;
}
Using a role (2)
use Student;
my $person = Student->new(
    name => 'Mike',
    dob => ... # yadda yadda
    course => 'CS',
);

$person->introduce();
> Hi, I'm Mike, age 45, studying CS
What we'd really like
use Student;
my $person = Student->new(
    name => 'Mike',
    dob => '05-08-1963',
    course => 'CS',
);
Redefine our attr...
package Age;
use Moose::Role;
has dob => (
    isa => 'DateStr',
    is =>'ro',
);
Types to the rescue

use Moose::Util::TypeConstraints;

subtype 'DateStr'
    => as 'Str'
    => where {
        /^dd-dd-dddd$/
    };
Types to the rescue (2)
use Moose::Util::TypeConstraints;
class_type 'DateTime';

coerce 'DateTime' => from 'Str'
   => via {
      my ($d, $m, $y) = split /-/, $_;
      return DateTime->new(
        year => $y, month => $m, day => $d
     );
  };
And then...
package Age;
use Moose::Role;
has dob => (
    isa => 'DateTime',
    is =>'ro',
    coerce => 1, # very important!
);
Et voila...
use Student;
my $person = Student->new(
    name => 'Mike',
    dob => '05-08-1963',
    course => 'CS',
);

print $person->age();
> 45
Roles as interfaces
package Earnings;
use Moose::Role;

requires qw/annual_income/;

sub monthly_income {
    return shift->annual_income / 12;
}
Roles as interfaces (2)
package Person;
with qw/Earnings/;

package Student;
extends qw/Person/;

sub annual_income {
   my $self = shift;
   return $self->grant_amount;
}
Role gotchas
Role gotchas

• Roles cannot use extends
Role gotchas

• Roles cannot use extends
• requires only works with actual methods :(
Role gotchas

• Roles cannot use extends
• requires only works with actual methods :(
 • for now, at least
Role gotchas

• Roles cannot use extends
• requires only works with actual methods :(
 • for now, at least
• watch out for method and attribute
  conflicts
Method Delegation
package Degree;
use Moose;
use Moose::Utils::TypeConstraints;
enum 'Grade' => qw/I IIi IIii III/;


has 'grade' => ( isa => 'Grade' );
has 'awarded' => (
    isa => 'DateTime',
    coerce => 1,
);
Method Delegation (2)
package Graduate;
use Moose;
extends qw/Student/;

has 'degree' => (
   isa => 'Degree',
   is => 'rw',
);
Method Delegation (3)
my $g = Graduate->new(name => 'Mike');
my $d = Degree->new(
    awarded => '06-06-1985',
    grade => 'IIii',
);
$g->degree($d);

print $g->degree->awarded->year;
> 1985
Method Delegation (4)
has 'degree' => (
   isa => 'Degree',
   is => 'rw',
   handles => {
       graduated => 'awarded'
   },
);
Method Delegation (5)
my $g = Graduate->new(name => 'Mike');
my $d = Degree->new(
    awarded => '06-06-1985',
    grade => 'IIii',
);
$g->degree($d);

print $g->graduated->year;
> 1985
More on attributes
package Student;
use MooseX::Util::TypeConstraints;
use Moose;
extends qw/Person/;
enum 'Result' => qw/pass fail/;
has classes => (
    isa => 'HashRef[Result]',
    is => 'rw',
    predicate => 'has_classes',
);
Attribute Helpers
my $st = Student->new( name => 'Mike' );

$st->classes(
    { "Compilers" => 'fail',
     "Numerical Methods" => 'pass' }
);

%{$st->classes}->{"Lisp"} = "pass";
Attribute Helpers (2)
use MooseX::AttributeHelpers;
has classes => (
    metaclass => 'Collection::Hash',
    isa => 'HashRef[Result]',
    is => 'rw',
    provides => {
        set => 'add_class',
        keys => 'list_classes',
    }
)
Attribute Helpers (3)
my $st = Student->new( name => 'Mike' );

$st->classes(
    { "Compilers" => 'fail',
      "Numerical Methods" => 'pass' }
);

$st->add_class("Lisp" => 'pass');
print join ", ", $st->list_classes();
> Compilers, Numerical Methods, Lisp
Introspecting Moose
Introspecting Moose
• my $metaclass = $self->meta;
Introspecting Moose
• my $metaclass = $self->meta;
Introspecting Moose
• my $metaclass = $self->meta;

• $metaclass->superclasses;
Introspecting Moose
• my $metaclass = $self->meta;

• $metaclass->superclasses;
• $metaclass->linearized_isa;
Introspecting Moose
• my $metaclass = $self->meta;

• $metaclass->superclasses;
• $metaclass->linearized_isa;
• $metaclass->has_method("foo");
Introspecting Moose
• my $metaclass = $self->meta;

• $metaclass->superclasses;
• $metaclass->linearized_isa;
• $metaclass->has_method("foo");
• $metaclass->get_all_attributes;
Method Signatures
Method Signatures

• We have types...
Method Signatures

• We have types...
• Wouldn't it be nice if types weren't
  restricted to attrs + accessors?
Method Signatures

• We have types...
• Wouldn't it be nice if types weren't
  restricted to attrs + accessors?
• Enter: MooseX::Method::Signature
Method Signatures
package Student;
use Moose;
use MooseX::Method::Signatures;

method attend (Str $class, DateTime
$time) {
     # ...
}
Method Signatures (2)
method attend
  (Str $class, DateTime $time) {
    if (grep $class,
        $self->list_classes) {
        $self->schedule($time, $class);
    }
}
Even more Java-like?
use MooseX::Declare;

class Student extends Person with
Earnings {
   has 'id' => ( isa => 'StudentID' );

    method attend ( Str $class, ... ) {
        # yadda yadda
    }
}
How is this
implemented?
Lasciate ogne
  speranza,
voi ch'intrate
But seriously...
But seriously...

• Devel::Declare sticks the interpreter on
  pause while it plays with your source
But seriously...

• Devel::Declare sticks the interpreter on
  pause while it plays with your source
• NOT a source filter
But seriously...

• Devel::Declare sticks the interpreter on
  pause while it plays with your source
• NOT a source filter
• You don't need to know what's going on...
Why Moose?
Why Moose?
• Less code = fewer errors
Why Moose?
• Less code = fewer errors
• Don't waste time on class implementation
Why Moose?
• Less code = fewer errors
• Don't waste time on class implementation
 • Better object model
Why Moose?
• Less code = fewer errors
• Don't waste time on class implementation
 • Better object model
 • "We do this so you don't have to"
Why Moose?
• Less code = fewer errors
• Don't waste time on class implementation
 • Better object model
 • "We do this so you don't have to"
 • Less need for low level tests
Why Moose?
• Less code = fewer errors
• Don't waste time on class implementation
 • Better object model
 • "We do this so you don't have to"
 • Less need for low level tests
• More descriptive code
Further Reading
Further Reading

• http://iinteractive.com/moose/
Further Reading

• http://iinteractive.com/moose/
• Moose::Cookbook (CPAN)
Further Reading

• http://iinteractive.com/moose/
• Moose::Cookbook (CPAN)
• http://www.stonehenge.com/merlyn/
  LinuxMag/col94.html
Complex Example
package Student;
use Moose;

# yadda

has 'id' => (
     isa => 'StudentID',
     is => 'rw',
);
Complex Example (2)
use MooseX::ClassAttribute;

class_has 'db' => (
    isa => 'Str', is => 'rw',
    default => 'dbi:SQLite:dbname=s.db'
);
class_has _schema => (
    isa => 'Person::Schema',
    lazy_build => 1, is => 'ro',
);
Complex Example (3)

sub _build__schema {
    my $self = shift;
    return Person::Schema->connect(
        $self->db
    );
}
Complex Example (4)
use Config::General;

override BUILDARGS => sub {
    my $args = super;

     my %conf = Config::General
         ->new( 'db.conf' )->getall();
     $args->{db} = $conf{db}
         if exists $conf{db};
};
Complex Example (5)
has _row => {
    isa => 'DBIx::Class::Row',
    lazy_build => 1,
}
sub _build__row {
    return shift->_schema
        ->resultset('Student')
        ->find($self->id);
}
Complex Example (6)

has _row => {
    isa => 'DBIx::Class::Row',
    lazy_build => 1,
    handles => [qw/address gender/],
}
Complex Example (7)
my $student = Student->new(
     name => 'Mike', id => '3056',
);

print $st->address();

# What happens here?
What happens?
What happens?
•   address method is handled by _row
What happens?
•   address method is handled by _row

•   _row is lazy_build, so calls _build__row
What happens?
•   address method is handled by _row

•   _row is lazy_build, so calls _build__row

• which requires _schema, ALSO
    lazy_build
What happens?
•   address method is handled by _row

•   _row is lazy_build, so calls _build__row

• which requires _schema, ALSO
    lazy_build

• which uses id to find the right row in db
What happens?
•   address method is handled by _row

•   _row is lazy_build, so calls _build__row

• which requires _schema, ALSO
    lazy_build

• which uses id to find the right row in db
•   Tadaa!
But...
# What if the student's ID changes?

has 'id' => (
    isa => 'StudentID',
    is => 'rw',
    trigger => '_build__row',
);

Weitere ähnliche Inhalte

Was ist angesagt?

A Few of My Favorite (Python) Things
A Few of My Favorite (Python) ThingsA Few of My Favorite (Python) Things
A Few of My Favorite (Python) ThingsMichael Pirnat
 
WordPress Cuztom Helper
WordPress Cuztom HelperWordPress Cuztom Helper
WordPress Cuztom Helperslicejack
 
Banishing Loops with Functional Programming in PHP
Banishing Loops with Functional Programming in PHPBanishing Loops with Functional Programming in PHP
Banishing Loops with Functional Programming in PHPDavid Hayes
 
WordCamp Portland 2018: PHP for WordPress
WordCamp Portland 2018: PHP for WordPressWordCamp Portland 2018: PHP for WordPress
WordCamp Portland 2018: PHP for WordPressAlena Holligan
 
Bioinformatics p5-bioperl v2013-wim_vancriekinge
Bioinformatics p5-bioperl v2013-wim_vancriekingeBioinformatics p5-bioperl v2013-wim_vancriekinge
Bioinformatics p5-bioperl v2013-wim_vancriekingeProf. Wim Van Criekinge
 
Модерни езици за програмиране за JVM (2011)
Модерни езици за програмиране за JVM (2011)Модерни езици за програмиране за JVM (2011)
Модерни езици за програмиране за JVM (2011)Bozhidar Batsov
 
Php 102: Out with the Bad, In with the Good
Php 102: Out with the Bad, In with the GoodPhp 102: Out with the Bad, In with the Good
Php 102: Out with the Bad, In with the GoodJeremy Kendall
 
Coffeescript: No really, it's just Javascript
Coffeescript: No really, it's just JavascriptCoffeescript: No really, it's just Javascript
Coffeescript: No really, it's just JavascriptBrian Mann
 
[WLDN] Supercharging word press development in 2018
[WLDN] Supercharging word press development in 2018[WLDN] Supercharging word press development in 2018
[WLDN] Supercharging word press development in 2018Adam Tomat
 
Transparent Object Persistence with FLOW3
Transparent Object Persistence with FLOW3Transparent Object Persistence with FLOW3
Transparent Object Persistence with FLOW3Karsten Dambekalns
 
Leveraging the Power of Graph Databases in PHP
Leveraging the Power of Graph Databases in PHPLeveraging the Power of Graph Databases in PHP
Leveraging the Power of Graph Databases in PHPJeremy Kendall
 
Leveraging the Power of Graph Databases in PHP
Leveraging the Power of Graph Databases in PHPLeveraging the Power of Graph Databases in PHP
Leveraging the Power of Graph Databases in PHPJeremy Kendall
 
Descobrindo a linguagem Perl
Descobrindo a linguagem PerlDescobrindo a linguagem Perl
Descobrindo a linguagem Perlgarux
 
Searching ORM: First Why, Then How
Searching ORM: First Why, Then HowSearching ORM: First Why, Then How
Searching ORM: First Why, Then Howsfarmer10
 
Contando uma história com O.O.
Contando uma história com O.O.Contando uma história com O.O.
Contando uma história com O.O.Vagner Zampieri
 
Rails for PHP Developers
Rails for PHP DevelopersRails for PHP Developers
Rails for PHP DevelopersRobert Dempsey
 

Was ist angesagt? (20)

A Few of My Favorite (Python) Things
A Few of My Favorite (Python) ThingsA Few of My Favorite (Python) Things
A Few of My Favorite (Python) Things
 
The jQuery Divide
The jQuery DivideThe jQuery Divide
The jQuery Divide
 
WordPress Cuztom Helper
WordPress Cuztom HelperWordPress Cuztom Helper
WordPress Cuztom Helper
 
Banishing Loops with Functional Programming in PHP
Banishing Loops with Functional Programming in PHPBanishing Loops with Functional Programming in PHP
Banishing Loops with Functional Programming in PHP
 
WordCamp Portland 2018: PHP for WordPress
WordCamp Portland 2018: PHP for WordPressWordCamp Portland 2018: PHP for WordPress
WordCamp Portland 2018: PHP for WordPress
 
Bioinformatics p5-bioperl v2013-wim_vancriekinge
Bioinformatics p5-bioperl v2013-wim_vancriekingeBioinformatics p5-bioperl v2013-wim_vancriekinge
Bioinformatics p5-bioperl v2013-wim_vancriekinge
 
Bioinformatica p6-bioperl
Bioinformatica p6-bioperlBioinformatica p6-bioperl
Bioinformatica p6-bioperl
 
Модерни езици за програмиране за JVM (2011)
Модерни езици за програмиране за JVM (2011)Модерни езици за програмиране за JVM (2011)
Модерни езици за програмиране за JVM (2011)
 
Perl object ?
Perl object ?Perl object ?
Perl object ?
 
Php 102: Out with the Bad, In with the Good
Php 102: Out with the Bad, In with the GoodPhp 102: Out with the Bad, In with the Good
Php 102: Out with the Bad, In with the Good
 
Coffeescript: No really, it's just Javascript
Coffeescript: No really, it's just JavascriptCoffeescript: No really, it's just Javascript
Coffeescript: No really, it's just Javascript
 
[WLDN] Supercharging word press development in 2018
[WLDN] Supercharging word press development in 2018[WLDN] Supercharging word press development in 2018
[WLDN] Supercharging word press development in 2018
 
Transparent Object Persistence with FLOW3
Transparent Object Persistence with FLOW3Transparent Object Persistence with FLOW3
Transparent Object Persistence with FLOW3
 
Leveraging the Power of Graph Databases in PHP
Leveraging the Power of Graph Databases in PHPLeveraging the Power of Graph Databases in PHP
Leveraging the Power of Graph Databases in PHP
 
Leveraging the Power of Graph Databases in PHP
Leveraging the Power of Graph Databases in PHPLeveraging the Power of Graph Databases in PHP
Leveraging the Power of Graph Databases in PHP
 
Descobrindo a linguagem Perl
Descobrindo a linguagem PerlDescobrindo a linguagem Perl
Descobrindo a linguagem Perl
 
Searching ORM: First Why, Then How
Searching ORM: First Why, Then HowSearching ORM: First Why, Then How
Searching ORM: First Why, Then How
 
Contando uma história com O.O.
Contando uma história com O.O.Contando uma história com O.O.
Contando uma história com O.O.
 
Rails for PHP Developers
Rails for PHP DevelopersRails for PHP Developers
Rails for PHP Developers
 
Django at Scale
Django at ScaleDjango at Scale
Django at Scale
 

Ähnlich wie Introduction to Moose with Moose Roles and Types

Moo the universe and everything
Moo the universe and everythingMoo the universe and everything
Moo the universe and everythingHenry Van Styn
 
P6 OO vs Moose (&Moo)
P6 OO vs Moose (&Moo)P6 OO vs Moose (&Moo)
P6 OO vs Moose (&Moo)lichtkind
 
Perl Teach-In (part 2)
Perl Teach-In (part 2)Perl Teach-In (part 2)
Perl Teach-In (part 2)Dave Cross
 
What's in a language? By Cheng Lou
What's in a language? By Cheng Lou What's in a language? By Cheng Lou
What's in a language? By Cheng Lou React London 2017
 
Moose - YAPC::NA 2012
Moose - YAPC::NA 2012Moose - YAPC::NA 2012
Moose - YAPC::NA 2012xSawyer
 
DBIx::Skinnyと仲間たち
DBIx::Skinnyと仲間たちDBIx::Skinnyと仲間たち
DBIx::Skinnyと仲間たちRyo Miyake
 
Perl: Hate it for the Right Reasons
Perl: Hate it for the Right ReasonsPerl: Hate it for the Right Reasons
Perl: Hate it for the Right ReasonsMatt Follett
 
Ruby 入門 第一次就上手
Ruby 入門 第一次就上手Ruby 入門 第一次就上手
Ruby 入門 第一次就上手Wen-Tien Chang
 
A Whirlwind Tour of Test::Class
A Whirlwind Tour of Test::ClassA Whirlwind Tour of Test::Class
A Whirlwind Tour of Test::ClassCurtis Poe
 
The Essential Perl Hacker's Toolkit
The Essential Perl Hacker's ToolkitThe Essential Perl Hacker's Toolkit
The Essential Perl Hacker's ToolkitStephen Scaffidi
 
Rubyforjavaprogrammers 1210167973516759-9
Rubyforjavaprogrammers 1210167973516759-9Rubyforjavaprogrammers 1210167973516759-9
Rubyforjavaprogrammers 1210167973516759-9sagaroceanic11
 
Rubyforjavaprogrammers 1210167973516759-9
Rubyforjavaprogrammers 1210167973516759-9Rubyforjavaprogrammers 1210167973516759-9
Rubyforjavaprogrammers 1210167973516759-9sagaroceanic11
 
Symfony & Javascript. Combining the best of two worlds
Symfony & Javascript. Combining the best of two worldsSymfony & Javascript. Combining the best of two worlds
Symfony & Javascript. Combining the best of two worldsIgnacio Martín
 
Ruby :: Training 1
Ruby :: Training 1Ruby :: Training 1
Ruby :: Training 1Pavel Tyk
 
Ruby 2: some new things
Ruby 2: some new thingsRuby 2: some new things
Ruby 2: some new thingsDavid Black
 
Active Support Core Extensions (1)
Active Support Core Extensions (1)Active Support Core Extensions (1)
Active Support Core Extensions (1)RORLAB
 
From Ruby to Scala
From Ruby to ScalaFrom Ruby to Scala
From Ruby to Scalatod esking
 
Objective C 基本介紹
Objective C 基本介紹Objective C 基本介紹
Objective C 基本介紹Giga Cheng
 
PHP-05-Objects.ppt
PHP-05-Objects.pptPHP-05-Objects.ppt
PHP-05-Objects.pptrani marri
 

Ähnlich wie Introduction to Moose with Moose Roles and Types (20)

Moo the universe and everything
Moo the universe and everythingMoo the universe and everything
Moo the universe and everything
 
P6 OO vs Moose (&Moo)
P6 OO vs Moose (&Moo)P6 OO vs Moose (&Moo)
P6 OO vs Moose (&Moo)
 
Perl Teach-In (part 2)
Perl Teach-In (part 2)Perl Teach-In (part 2)
Perl Teach-In (part 2)
 
What's in a language? By Cheng Lou
What's in a language? By Cheng Lou What's in a language? By Cheng Lou
What's in a language? By Cheng Lou
 
Moose - YAPC::NA 2012
Moose - YAPC::NA 2012Moose - YAPC::NA 2012
Moose - YAPC::NA 2012
 
DBIx::Skinnyと仲間たち
DBIx::Skinnyと仲間たちDBIx::Skinnyと仲間たち
DBIx::Skinnyと仲間たち
 
Perl: Hate it for the Right Reasons
Perl: Hate it for the Right ReasonsPerl: Hate it for the Right Reasons
Perl: Hate it for the Right Reasons
 
Ruby 入門 第一次就上手
Ruby 入門 第一次就上手Ruby 入門 第一次就上手
Ruby 入門 第一次就上手
 
A Whirlwind Tour of Test::Class
A Whirlwind Tour of Test::ClassA Whirlwind Tour of Test::Class
A Whirlwind Tour of Test::Class
 
The Essential Perl Hacker's Toolkit
The Essential Perl Hacker's ToolkitThe Essential Perl Hacker's Toolkit
The Essential Perl Hacker's Toolkit
 
Rubyforjavaprogrammers 1210167973516759-9
Rubyforjavaprogrammers 1210167973516759-9Rubyforjavaprogrammers 1210167973516759-9
Rubyforjavaprogrammers 1210167973516759-9
 
Rubyforjavaprogrammers 1210167973516759-9
Rubyforjavaprogrammers 1210167973516759-9Rubyforjavaprogrammers 1210167973516759-9
Rubyforjavaprogrammers 1210167973516759-9
 
Symfony & Javascript. Combining the best of two worlds
Symfony & Javascript. Combining the best of two worldsSymfony & Javascript. Combining the best of two worlds
Symfony & Javascript. Combining the best of two worlds
 
Ruby :: Training 1
Ruby :: Training 1Ruby :: Training 1
Ruby :: Training 1
 
Ruby 2: some new things
Ruby 2: some new thingsRuby 2: some new things
Ruby 2: some new things
 
Ruby 101
Ruby 101Ruby 101
Ruby 101
 
Active Support Core Extensions (1)
Active Support Core Extensions (1)Active Support Core Extensions (1)
Active Support Core Extensions (1)
 
From Ruby to Scala
From Ruby to ScalaFrom Ruby to Scala
From Ruby to Scala
 
Objective C 基本介紹
Objective C 基本介紹Objective C 基本介紹
Objective C 基本介紹
 
PHP-05-Objects.ppt
PHP-05-Objects.pptPHP-05-Objects.ppt
PHP-05-Objects.ppt
 

Kürzlich hochgeladen

How to convert PDF to text with Nanonets
How to convert PDF to text with NanonetsHow to convert PDF to text with Nanonets
How to convert PDF to text with Nanonetsnaman860154
 
Automating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps ScriptAutomating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps Scriptwesley chun
 
Scaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationScaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationRadu Cotescu
 
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Drew Madelung
 
Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024The Digital Insurer
 
CNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of ServiceCNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of Servicegiselly40
 
Factors to Consider When Choosing Accounts Payable Services Providers.pptx
Factors to Consider When Choosing Accounts Payable Services Providers.pptxFactors to Consider When Choosing Accounts Payable Services Providers.pptx
Factors to Consider When Choosing Accounts Payable Services Providers.pptxKatpro Technologies
 
A Call to Action for Generative AI in 2024
A Call to Action for Generative AI in 2024A Call to Action for Generative AI in 2024
A Call to Action for Generative AI in 2024Results
 
The Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptxThe Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptxMalak Abu Hammad
 
Presentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreterPresentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreternaman860154
 
Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024The Digital Insurer
 
[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdfhans926745
 
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Miguel Araújo
 
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptxHampshireHUG
 
Data Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt RobisonData Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt RobisonAnna Loughnan Colquhoun
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerThousandEyes
 
Artificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and MythsArtificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and MythsJoaquim Jorge
 
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking MenDelhi Call girls
 
A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)Gabriella Davis
 
Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)wesley chun
 

Kürzlich hochgeladen (20)

How to convert PDF to text with Nanonets
How to convert PDF to text with NanonetsHow to convert PDF to text with Nanonets
How to convert PDF to text with Nanonets
 
Automating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps ScriptAutomating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps Script
 
Scaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationScaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organization
 
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
 
Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024
 
CNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of ServiceCNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of Service
 
Factors to Consider When Choosing Accounts Payable Services Providers.pptx
Factors to Consider When Choosing Accounts Payable Services Providers.pptxFactors to Consider When Choosing Accounts Payable Services Providers.pptx
Factors to Consider When Choosing Accounts Payable Services Providers.pptx
 
A Call to Action for Generative AI in 2024
A Call to Action for Generative AI in 2024A Call to Action for Generative AI in 2024
A Call to Action for Generative AI in 2024
 
The Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptxThe Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptx
 
Presentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreterPresentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreter
 
Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024
 
[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf
 
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
 
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
 
Data Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt RobisonData Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt Robison
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected Worker
 
Artificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and MythsArtificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and Myths
 
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
 
A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)
 
Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)
 

Introduction to Moose with Moose Roles and Types