Peczenyj's Blog

Just Another /Perl|Ruby|C++|Java|Python|JavaScript|Flash|Bash/ Hacker

MooseX - a New Ruby DSL for Object Oriented Programming (and Much More)

MooseX is a postmodern object DSL for Ruby Build Status Gem Version

This is a DSL for object creation, aspects, method delegation and much more. It is based on Perl Moose and Moo, two important modules who add a better way of Object Orientation development (and I enjoy A LOT). Using a declarative stype, using Moose/Moo you can create attributes, methods, the entire constructor and much more. But I can’t find something similar in Ruby world, so I decide port a small subset of Moose to create a powerfull DSL for object construction.

Of course, there is few similar projects in ruby like

But the objetive of MooseX is different: this is a toolbox to create Classes based on DSL, with unique features like

  • method delegation ( see ‘handles’)
  • lazy attributes
  • roles
  • parameterized roles
  • composable type check
  • events

and much more.

This rubygem is based on this modules:

See also:

  • Joose, a javascript port of Moose.
  • Perl 6 Perl 6 OO programming style.

Why MooseX? Because the namespace MooseX/MooX is open to third-party projects/plugins/extensions. You can upgrade your Moo(se) class using other components if you want. And there is one gem called ‘moose’ :/

THIS MODULE IS EXPERIMENTAL YET! BE CAREFUL!

Talk is cheap. Show me the code!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
require 'moosex'

class Point
  include MooseX

  has x: {
    is: :rw,      # read-write (mandatory)
    isa: Integer, # should be Integer
    default: 0,   # default value is 0 (constant)
  }

  has y: {
    is: :rw,
    isa: Integer,
    default: lambda { 0 }, # you should specify a lambda
  }

  def clear!
    self.x= 0     # to run with type-check you must
    self.y= 0     # use the setter instad @x=
  end
end

# now you have a generic constructor
p1  = Point.new                       # x and y will be 0
p2  = Point.new( x:  5 )              # y will be 0
p3  = Point.new( x:  5, y: 4)

Adding a ‘Dry Run’ Capability to Your Moose Class With MooseX::Role::DryRunnable

A ‘dry run’ is a testing process where the effects of a possible failure are intentionally mitigated. For example, an aerospace company may conduct a “dry run” test of a jet’s new pilot ejection seat while the jet is parked on the ground, rather than while it is in flight. Or, in software development, we can change the behavior of some methods in order to test, like avoid change data into a database (logging the action instead).

There are many ways to implement this capability. For example, we can add an explicity return in each method and test some condition. I will show some options in this article and we will find how to use the module MooseX::Role::DryRunnable in our Moose classes (Perl).

One simple example in Perl, reading from an environment variable DRY_RUN.

1
2
3
4
5
6
7
package Foo;

sub bar {
  logger->debug("Foo::bar @_");
  return if $ENV{'DRY_RUN'};
  ...
}

Lazy::Bool My First Module in CPAN

Lazy::Bool is my first module in CPAN (The Comprehensive Perl Archive Network). It is a simple module (only 60 lines) and few methods/operators but can be useful in some situation. The source code can be found in my github.

Example

1
2
3
4
5
6
7
8
9
10
11
12
13
use Lazy::Bool;
use Test::More tests=> 3;
my $a = 6;
my $b = 4;
my $x  = Lazy::Bool->new(sub{ $a > $b });
my $false = Lazy::Bool::false;

my $result = ($x | $false) & ( ! ( $false & ! $false ) );

# now the expressions will be evaluate
ok($result,    "complex expression should be true");
ok(!! $x ,  "double negation of true value should be true");
ok(!!! $false, "truple negation of false value should be true");

Schwartzian Transform

I will show in this post one of the most useful things that I learn in Perl: the famous Schwartzian transform. With examples in Ruby

In computer science, the Schwartzian transform is a Perl programming idiom used to improve the efficiency of sorting a list of items. This idiom is appropriate for comparison-based sorting when the ordering is actually based on the ordering of a certain property (the key) of the elements, where computing that property is an intensive operation that should be performed a minimal number of times. The Schwartzian Transform is notable in that it does not use named temporary arrays.