Introducing Moops

Moops is sugar for writing object-oriented Perl. It provides similar syntax to MooseX::Declare and Stevan Little's p5-mop-redux. It's some glue between Moo, Type::Tiny, Function::Parameters and Try::Tiny, but for those occasions when you want the backing of a meta object protocol, allows you to easily swap Moose (or even Mouse) in place of Moo with very minimal changes.

Here's an example of a complete, usable class definition in Moops:

   use Moops;
   
   class Person :ro {
      has first_name => (isa => Str);
      has last_name  => (isa => Str);
   }

Note the :ro shortcut, to make attributes default to being read-only. Boilerplate code like use namespace::sweep and __PACKAGE__->meta->make_immutable can be omitted because Moops does that all for you.

Here's a more extensive example, showing off some other Moops features.

   class User extends Person using Moose :ro {
      use DateTime ();
      
      has password    => (isa => Str);
      has last_login  => (
         is      => 'rwp',
         isa     => InstanceOf['DateTime'],
         handles => { 'date_of_last_login' => 'date' },
      );
      
      method login ( Str $pw ) {
         return 0 if $pw ne $self->password;
         $self->_set_last_login( DateTime->now );
         return 1;
      }
   }

Moops goes to great lengths to smooth over the differences between Moo and Moose. Type constraints are taken from Types::Standard, so the same types will be available for attribute declarations and method signatures, no matter whether you're using Moo, Moose or Mouse. The Moo-specific is => 'rwp' is munged by MooseX::MungeHas into something Moose is capable of understanding.

Roles can be declared and used just as easily:

   role Breakable :rwp {
      has is_broken => (isa => Bool);
      after break () {
         $self->_set_is_broken(1);
      }
   }
   
   class Engine;
   
   class Car with Breakable {
      
      has engine    => (is => 'ro', isa => InstanceOf['Engine']);
      has is_moving => (is => 'rw', isa => Bool);
      
      method start () {
         return if $self->is_broken;
         say "Starting car";
         $self->is_moving(1);
      }
      
      method stop () {
         say "Stopping car";
         $self->is_moving(0);
      }
      
      method break () {
         say "Car broke";
         $self->stop if $self->is_moving;
      }
   }

Moops is still in an early stage of development, but loads and runs significantly faster than MooseX::Declare and doesn't seem to suffer from as many parsing oddities. If you've got a few spare minutes, and a relatively up-to-date Perl installation (Perl 5.14 is required), please download it and give it a go, and let me know how it went for you.

8 Comments

This looks exciting. It is good to see that it is much faster than MooseX::Declare.

How does Moops do method signatures?

I see now - Function::Parameters

can you fix the lines in the error messages?

Looks like a good starting point to teach modern/object-oriented Perl. The current documentation, however, is more useful to insiders that already know and care about existing frameworks (Moose, Mouse, Moo, p5-moo, Class::Tiny...) with all of their confusing extensions. I hope we'll some day get a Moops tutorial that avoids any (!) references to other Perl modules but just explains syntax and features of Moops. Don't get me wrong, the current documentation is good, but it aims at Perl-enthusiasts. Other programmers just want to know how to code with Moops to solve problems. They are not interested on historical details which feature was inspired by what other package and how things used to be in Perl the old days ;-)

It might help to explicitly compare Moops with other programming languages instead of comparing it with other Perl modules.

nice, I will try it :)

Is there a reason for preferring Moo instead of Mouse?

Leave a comment

About Toby Inkster

user-pic I'm tobyink on CPAN, IRC and PerlMonks.