NAME
    Acme::Modo - An attempt at a Modern Perl 5 implementation

DESCRIPTION
    There is no real description for this module, hence why it's in the
    Acme::* namespace. It gives you the features to perform perl5 in a..
    different way. It makes data type classes available (Int, Str and Array)
    and adds extra methods. You can even turn your package into a fully
    working object, if you wish. This module is still very experimental.

SYNOPSIS
        # Use / to split a string and return an Array class
        # You can do it all inline too, if you wish
        my $str = Str->new("player=Arthas;class=Spellsword;race=Imperial");
        ($str / ';')->loop(sub {
            my ($key, $val) = (Str->new($_) / '=')->val;
            say "$key = $val";
        });

DATA TYPE CLASSES
    There are currently 3 classes; Str, Int and Array. Each have their own
    overloaded operators to perform different actions, or you can use it the
    object way.

  Str
    From the synopsis ypu cam see to create a Str you just need to

        my $str = Str->new("Some fancy string here");

    Now, in my mind, strings shouldn't be allowed to perform math. That's
    just weird.

        my $arr = $str / ':' # splits a string using the ':' delimeter, returning an Array class
        $str = $str + " How" + " are" + " you?"; # adds extra strings to your current string

    You can even set multiple Str classes in one hit. Using "say" then a Str
    object will just print its value to the screen, not return the object

        sub name {
            my ($first, $last) = Str->new(@_);
            say $first; # prints Foo
            say $last;  # prints Bar
        }

        name "Foo", "Bar";

  Int
    These ones aren't very interesting yet. I haven't done a lot with them,
    but they are then when I'm ready to extend them.

  Array
    Initialisation is easy enough..

        my $arr = Array->new(1..6);
        my $arr = Array->new(qw( Hello there world ));

    You can loop through an Array with "loop"

        my $arr = Array->new(1..5);
        $arr->loop(sub {
            say $_;
        });

    Push items to it (takes a reference)

        my $arr = Array->new('Hello');
        # $arr = $arr + ['something'];
        ($arr + [' World'])->loop(sub {
            say $_;
        });

    Inserting will add an element to the beginning

        $arr = $arr << ['Boing'];

    Matching is fairly easy too

        my $day = 'Tuesday';
        my $weekdays = Array->new(qw< Monday Tuesday Wednesday Thursday Friday >);
    
        say "See you on $day"
            if $weekdays ~~ $day;

  Method
    This one isn't really a data class. Infact it doesn't do much, but you
    may find it useful. It allows you to create a method on the fly, inject
    to the current package, run it or push it into another class.

        my $method = Method->new(sub {
            my ($class, $name) = @_;
            $name = $class if !$name;
            say "Hello, ${name};
        });

    Now, we can use "inject" to add the new subroutine into the currect
    package. The only argument it takes is the name of the subroutine.

        $method->inject('foo');
        foo("World");
        __PACKAGE__->foo("World"); # prints Hello, World

    Or, we can use "push" to inject it into a different class.

        use FooClass;
    
        $method->push(
            to => 'FooClass',
            as => 'foo'
        );

        FooClass->foo("World"); # prints Hello, World

    Using "run" you can execute the subroutine, which it will then return
    the results. Arguments to "run" are actually the arguments you want to
    pass to the subroutine.

        say $method->run("World", "Something else", "Foo");

OBJECT BUILDING
    Turning Modo into a working class is simple.

        package MyFoo;
        use Modo as => 'Class';
    
        1;

    Above is a fully working class.. that doesn't do much, really. It
    injects the method 'new' for you, and also imports some class-only
    methods like "has" and "extends". Those familiar with modules like Moose
    will know what I'm talking about. "has" creates a read-writable, or
    read-only accessor, and "extends" will inherit another class.

        {
            package MyFoo;
            use Modo as => 'Class';
    
            has 'x' => ( is => 'rw', default => 5 );
        }

        my $foo = MyFoo->new;
        say $foo->x; # prints 5
    
        $foo->x(7); # updates x to 7
        say $foo->x; # prints 7

    As you can see it supports minimal features from dedicated OOP
    frameworks, like "rw" (Read-Writable) and "ro" (Read-Only) accessors.

METHODS
  private
    We can create "private" methods, which means that method cannot be
    called by anything outside of the class it lives in. For example,

        {
            package MyFoo;
    
            use Acme::Modo as => 'Class';
    
            private 'baz' => sub {
                say "Hello, World!";
            };
        }
    
        my $foo = MyFoo->new;
        $foo->baz; # throws a warning

    However, if we create a method that calls it from within itself..

        sub callbaz {
            this->baz;
        }

    then..

        $foo->callbaz; # prints Hello, World!

    This seems to be OK because we called a public method that ran the
    private method for us. Oh, by the way, you can use "this" to return the
    package name.

  enum
    Let's take a look at the "enum" method. I wanted something similar to
    perl6's enum, but done in perl5-style. With this we can create constants
    out of dynamically generated classes. Say we wanted to create our very
    own Boolean type.. yeah, we can do that.

        use Acme::Modo;

        enum Bool => ( 'True:1', 'False:0' );

        # set up a couple of test methods to test against our new Boolean type
        sub ok { return 1; }
        sub not_ok { return 0; }

        if (ok() == Bool->True) { say "We're good!"; }
        if (not_ok() == Bool->False) { say "This is false"; }

    If you seperate an element with ':', then the value to the right will
    become the value of the method. If you omit this, then it will be the
    number of position in the list. For example, if we omited the 1 and 0
    from our True and False elements, then True would have returned '1' and
    False would have returned '2'.

  lambda
    Not really a proper lambda, I guess. But I wasn't sure what else to name
    it. This works on arrayrefs or hashrefs, simply pass it a block, then
    the ref and it will iterate through it while passing the value, or key
    and value if applicable as arguments. You know, this almost resembles a
    "map {}". Oh well.

        # print 1 to 5
        lambda {
            say $_[0];
        } [ 1..5 ];

        # or you can do hashrefs
        my $h = {
            name  => 'Foo',
            age   => 5,
            place => 'Perl Land'
        };

        lambda {
            my ($key, $val) = @_;
            say "Key: $key";
            say "Value: $val";
        } $h;

  clone
    "clone" can be performed on most data type classes (ie: Array, Str and
    Int). It creates a copy of the instance so you can perform actions
    without mutating the original object.

        my $str = Str->new("Hello");
        say $str->clone->concat(", World");
        say $str;

        # outputs:
        # Hello, World
        # Hello

  prompt
    Takes user input and returns it. This will also chomp the newline from
    the end for you. It takes two arguments, the last one being optional.
    The first argument is a line of text to present to the user before the
    STDIN is taken, the second, if you pass a -1 it will not add a newline
    to the end of the string sent.

        my $name = prompt("Please enter your name: ", -1);
        say "Hello, ${name}!";

        my $stuff = prompt("Type stuff below");
        say "You said: ${stuff}";

  size
    This is another data type method you can use on Strings, Integers and
    Arrays. For strings, it will return the length of the string. With
    Arrays it will return the number of elements, and it just returns the
    integer as itself. Useless, right?

        my $arr = Array->new(qw< a b c d e >);
        say $arr->size;

  WHAT
    Call this on any data type method to get its type. For example,

        my $this = Str->new("Hey");
        my $that = Array->new(1..6);
    
        say $this->WHAT; # Str
        say $that->WHAT; # Array

CONDITIONALS
    A new type of class in Acme::Modo is "Conditionals". Basically, instead
    of writing an "if" statement with a large number of tests, you can
    convert them all into one conditional and test that. As it creates a
    class per-conditional you can share them anywhere and resume them.

        # The conditional below would fail
        # because one of the tests equals 0
        conditional 'MyCond' => (
            this_method(),
            that_method(),
            10-10,
        );

        if (Conditional->MyCond) {
            say "We're good :-)";
        }
        else {
            say "There was a problem";
        }

    When you call "Conditional", it will run through every test, and if any
    are false (equal to 0), then it returns 0 itself. If they all pass, it
    will return 1 for true.

AUTHOR
    Brad Haywood <brad@perlpowered.com>

LICENSE
    This library is free software. You can redistribute it and/or modify it
    under the same terms as Perl itself.

