Venus::Mixin
Mixin Builder
Mixin Builder for Perl 5
function: after function: around function: attr function: base function: before function: catch function: error function: false function: from function: handle function: hook function: mask function: mixin function: raise function: role function: test function: true function: with
package Person;
use Venus::Class 'attr';
attr 'fname';
attr 'lname';
package Identity;
use Venus::Mixin 'attr';
attr 'id';
attr 'login';
attr 'password';
sub EXPORT {
# explicitly declare routines to be consumed
['id', 'login', 'password']
}
package Authenticable;
use Venus::Role;
sub authenticate {
return true;
}
sub AUDIT {
my ($self, $from) = @_;
# ensure the caller has a login and password when consumed
die "${from} missing the login attribute" if !$from->can('login');
die "${from} missing the password attribute" if !$from->can('password');
}
sub BUILD {
my ($self, $data) = @_;
$self->{auth} = undef;
return $self;
}
sub EXPORT {
# explicitly declare routines to be consumed
['authenticate']
}
package User;
use Venus::Class;
base 'Person';
mixin 'Identity';
attr 'email';
test 'Authenticable';
sub valid {
my ($self) = @_;
return $self->login && $self->password ? true : false;
}
package main;
my $user = User->new(
fname => 'Elliot',
lname => 'Alderson',
);
# bless({fname => 'Elliot', lname => 'Alderson'}, 'User')
This package provides a mixin builder which when used causes the consumer to inherit from Venus::Core::Mixin which provides mixin building and lifecycle hooks. A mixin can do almost everything that a role can do but differs from a "role" in that whatever routines are declared using "export" will be exported and will overwrite routines of the same name in the consumer.
The after function installs a method modifier that executes after the original method, allowing you to perform actions after a method call. Note: The return value of the modifier routine is ignored; the wrapped method always returns the value from the original method. Modifiers are executed in the order they are stacked. This function is only exported when requested.
after(string $name, coderef $code) (coderef)
{ since => '4.15', }
=example-1 after
package Example1;
use Venus::Mixin 'after', 'attr';
attr 'calls';
sub BUILD {
my ($self) = @_;
$self->calls([]);
}
sub execute {
my ($self) = @_;
push @{$self->calls}, 'original';
return 'original';
}
after 'execute', sub {
my ($self) = @_;
push @{$self->calls}, 'after';
return 'ignored';
};
sub EXPORT {
['execute', 'calls', 'BUILD']
}
package Consumer;
use Venus::Class;
mixin 'Example1';
package main;
my $example = Consumer->new;
my $result = $example->execute;
# "original"
The around function installs a method modifier that wraps around the original method. The callback provided will recieve the original routine as its first argument. This function is only exported when requested.
around(string $name, coderef $code) (coderef)
{ since => '4.15', }
=example-1 around
package Example2;
use Venus::Mixin 'around', 'attr';
sub process {
my ($self, $value) = @_;
return $value;
}
around 'process', sub {
my ($orig, $self, $value) = @_;
return $self->$orig($value) * 2;
};
sub EXPORT {
['process']
}
package Consumer2;
use Venus::Class;
mixin 'Example2';
package main;
my $result = Consumer2->new->process(5);
# 10
The attr function creates attribute accessors for the calling package. This function is always exported unless a routine of the same name already exists.
attr(string $name) (string)
{ since => '1.00', }
=example-1 attr
package Example;
use Venus::Mixin;
attr 'name';
# "Example"
The before function installs a method modifier that executes before the original method, allowing you to perform actions before a method call. Note: The return value of the modifier routine is ignored; the wrapped method always returns the value from the original method. Modifiers are executed in the order they are stacked. This function is only exported when requested.
before(string $name, coderef $code) (coderef)
{ since => '4.15', }
=example-1 before
package Example3;
use Venus::Mixin 'attr', 'before';
attr 'calls';
sub perform {
my ($self) = @_;
push @{$self->calls}, 'original';
return $self;
}
before 'perform', sub {
my ($self) = @_;
push @{$self->calls}, 'before';
return $self;
};
sub EXPORT {
['perform']
}
package Consumer3;
use Venus::Class;
attr 'calls';
sub BUILD {
my ($self) = @_;
$self->calls([]);
}
mixin 'Example3';
package main;
my $example = Consumer3->new;
$example->perform;
my $calls = $example->calls;
# ['before', 'original']
The base function registers one or more base classes for the calling package. This function is always exported unless a routine of the same name already exists.
base(string $name) (string)
{ since => '1.00', }
=example-1 base
package Entity;
use Venus::Class;
sub output {
return;
}
package Example;
use Venus::Mixin;
base 'Entity';
# "Example"
The catch function executes the code block trapping errors and returning the caught exception in scalar context, and also returning the result as a second argument in list context. This function isn't export unless requested.
catch(coderef $block) (Venus::Error, any)
{ since => '1.02', }
=example-1 catch
package Ability;
use Venus::Mixin 'catch';
sub attempt_catch {
catch {die};
}
sub EXPORT {
['attempt_catch']
}
package Example;
use Venus::Class 'with';
mixin 'Ability';
package main;
my $example = Example->new;
my $error = $example->attempt_catch;
$error;
# "Died at ..."
The error function throws a Venus::Error exception object using the exception object arguments provided. This function isn't export unless requested.
error(maybe[hashref] $args) (Venus::Error)
{ since => '1.02', }
=example-1 error
package Ability;
use Venus::Mixin 'error';
sub attempt_error {
error;
}
sub EXPORT {
['attempt_error']
}
package Example;
use Venus::Class 'with';
with 'Ability';
package main;
my $example = Example->new;
my $error = $example->attempt_error;
# bless({...}, 'Venus::Error')
The false function returns a falsy boolean value which is designed to be practically indistinguishable from the conventional numerical 0 value. This function is always exported unless a routine of the same name already exists.
false() (boolean)
{ since => '1.00', }
=example-1 false
package Example;
use Venus::Mixin;
my $false = false;
# 0
The from function registers one or more base classes for the calling package and performs an "audit". This function is always exported unless a routine of the same name already exists.
from(string $name) (string)
{ since => '1.00', }
=example-1 from
package Entity;
use Venus::Role;
attr 'startup';
attr 'shutdown';
sub EXPORT {
['startup', 'shutdown']
}
package Record;
use Venus::Class;
sub AUDIT {
my ($self, $from) = @_;
die "Missing startup" if !$from->can('startup');
die "Missing shutdown" if !$from->can('shutdown');
}
package Example;
use Venus::Class;
with 'Entity';
from 'Record';
# "Example"
The handle function installs a method modifier that wraps a method, providing low-level control. The callback provided will recieve the original routine as its first argument (or undef if the source routine doesn't exist). This function is only exported when requested.
handle(string $name, coderef $code) (coderef)
{ since => '4.15', }
=example-1 handle
package Example4;
use Venus::Mixin 'handle';
sub compute {
my ($self, $value) = @_;
return $value;
}
handle 'compute', sub {
my ($orig, $self, $value) = @_;
return $orig ? $self->$orig($value * 2) : 0;
};
sub EXPORT {
['compute']
}
package Consumer4;
use Venus::Class;
mixin 'Example4';
package main;
my $result = Consumer4->new->compute(5);
# 10
The hook function installs a method modifier on a lifecycle hook method. The first argument is the type of modifier desired, e.g., "before", "after", "around", and the callback provided will recieve the original routine as its first argument. This function is only exported when requested.
hook(string $type, string $name, coderef $code) (coderef)
{ since => '4.15', }
=example-1 hook
package Example5;
use Venus::Mixin 'attr', 'hook';
attr 'startup';
sub BUILD {
my ($self, $args) = @_;
$self->startup('original');
}
hook 'after', 'build', sub {
my ($self) = @_;
$self->startup('modified');
};
sub EXPORT {
['startup', 'BUILD']
}
package Consumer5;
use Venus::Class;
mixin 'Example5';
package main;
my $result = Consumer5->new->startup;
# "modified"
The mask function creates private attribute accessors that can only be accessed from within the class or its subclasses. This function is exported on-demand unless a routine of the same name already exists.
mask(string $name) (string)
{ since => '4.15', }
=example-1 mask
package Example;
use Venus::Mixin;
mask 'cache';
sub get_cache {
my ($self) = @_;
return $self->cache;
}
sub set_cache {
my ($self, $value) = @_;
$self->cache($value);
}
sub EXPORT {
['cache', 'get_cache', 'set_cache']
}
package Consumer;
use Venus::Class;
mixin 'Example';
package main;
my $consumer = Consumer->new;
The mixin function registers and consumes mixins for the calling package. This function is always exported unless a routine of the same name already exists.
mixin(string $name) (string)
{ since => '1.02', }
=example-1 mixin
package YesNo;
use Venus::Mixin;
sub no {
return 0;
}
sub yes {
return 1;
}
sub EXPORT {
['no', 'yes']
}
package Answer;
use Venus::Mixin;
mixin 'YesNo';
# "Answer"
The raise function generates and throws a named exception object derived from Venus::Error, or provided base class, using the exception object arguments provided. This function isn't export unless requested.
raise(string $class | tuple[string, string] $class, maybe[hashref] $args) (Venus::Error)
{ since => '1.02', }
=example-1 raise
package Ability;
use Venus::Mixin 'raise';
sub attempt_raise {
raise 'Example::Error';
}
sub EXPORT {
['attempt_raise']
}
package Example;
use Venus::Class 'with';
with 'Ability';
package main;
my $example = Example->new;
my $error = $example->attempt_raise;
# bless({...}, 'Example::Error')
The role function registers and consumes roles for the calling package. This function is always exported unless a routine of the same name already exists.
role(string $name) (string)
{ since => '1.00', }
=example-1 role
package Ability;
use Venus::Role;
sub action {
return;
}
package Example;
use Venus::Class;
role 'Ability';
# "Example"
The test function registers and consumes roles for the calling package and performs an "audit", effectively allowing a role to act as an interface. This function is always exported unless a routine of the same name already exists.
test(string $name) (string)
{ since => '1.00', }
=example-1 test
package Actual;
use Venus::Role;
package Example;
use Venus::Class;
test 'Actual';
# "Example"
The true function returns a truthy boolean value which is designed to be practically indistinguishable from the conventional numerical 1 value. This function is always exported unless a routine of the same name already exists.
true() (boolean)
{ since => '1.00', }
=example-1 true
package Example;
use Venus::Class;
my $true = true;
# 1
The with function registers and consumes roles for the calling package. This function is an alias of the "test" function and will perform an "audit" if present. This function is always exported unless a routine of the same name already exists.
with(string $name) (string)
{ since => '1.00', }
=example-1 with
package Understanding;
use Venus::Role;
sub knowledge {
return;
}
package Example;
use Venus::Class;
with 'Understanding';
# "Example"
t/Venus.t: present: authors t/Venus.t: present: license
67 POD Errors
The following errors were encountered while parsing the POD:
- Around line 14:
Unknown directive: =name
- Around line 22:
Unknown directive: =tagline
- Around line 30:
Unknown directive: =abstract
- Around line 38:
Unknown directive: =includes
- Around line 63:
Unknown directive: =synopsis
- Around line 162:
Unknown directive: =description
- Around line 175:
Unknown directive: =function
- Around line 183:
Unknown directive: =signature
- Around line 187:
Unknown directive: =metadata
- Around line 245:
Unknown directive: =function
- Around line 251:
Unknown directive: =signature
- Around line 255:
Unknown directive: =metadata
- Around line 303:
Unknown directive: =function
- Around line 308:
Unknown directive: =signature
- Around line 312:
Unknown directive: =metadata
- Around line 342:
Unknown directive: =function
- Around line 350:
Unknown directive: =signature
- Around line 354:
Unknown directive: =metadata
- Around line 415:
Unknown directive: =function
- Around line 421:
Unknown directive: =signature
- Around line 425:
Unknown directive: =metadata
- Around line 462:
Unknown directive: =function
- Around line 468:
Unknown directive: =signature
- Around line 472:
Unknown directive: =metadata
- Around line 518:
Unknown directive: =function
- Around line 523:
Unknown directive: =signature
- Around line 527:
Unknown directive: =metadata
- Around line 573:
Unknown directive: =function
- Around line 579:
Unknown directive: =signature
- Around line 583:
Unknown directive: =metadata
- Around line 619:
=cut found outside a pod block. Skipping to next block.
- Around line 629:
Unknown directive: =function
- Around line 635:
Unknown directive: =signature
- Around line 639:
Unknown directive: =metadata
- Around line 691:
Unknown directive: =function
- Around line 698:
Unknown directive: =signature
- Around line 702:
Unknown directive: =metadata
- Around line 750:
Unknown directive: =function
- Around line 757:
Unknown directive: =signature
- Around line 761:
Unknown directive: =metadata
- Around line 811:
Unknown directive: =function
- Around line 817:
Unknown directive: =signature
- Around line 821:
Unknown directive: =metadata
- Around line 875:
Unknown directive: =function
- Around line 880:
Unknown directive: =signature
- Around line 884:
Unknown directive: =metadata
- Around line 966:
=cut found outside a pod block. Skipping to next block.
- Around line 979:
Unknown directive: =function
- Around line 985:
Unknown directive: =signature
- Around line 989:
Unknown directive: =metadata
- Around line 1036:
Unknown directive: =function
- Around line 1041:
Unknown directive: =signature
- Around line 1045:
Unknown directive: =metadata
- Around line 1102:
=cut found outside a pod block. Skipping to next block.
- Around line 1113:
Unknown directive: =function
- Around line 1120:
Unknown directive: =signature
- Around line 1124:
Unknown directive: =metadata
- Around line 1172:
=cut found outside a pod block. Skipping to next block.
- Around line 1182:
Unknown directive: =function
- Around line 1188:
Unknown directive: =signature
- Around line 1192:
Unknown directive: =metadata
- Around line 1228:
=cut found outside a pod block. Skipping to next block.
- Around line 1238:
Unknown directive: =function
- Around line 1245:
Unknown directive: =signature
- Around line 1249:
Unknown directive: =metadata
- Around line 1306:
=cut found outside a pod block. Skipping to next block.
- Around line 1317:
Unknown directive: =partials