MooseX::Extended(3)
π MooseX::Extended π
okay bestie, so this is MooseX::Extended(3) β it's a User Contributed Perl Documentation page, and it's about to become your whole personality. sit down, hydrate, let's go β¨
πΈ NAME πΈ
MooseX::Extended β extend Moose with safe defaults and useful features. no cap, that's literally what it says.
π VERSION π
version 0.35
β¨ SYNOPSIS β¨
okay so here's the whole vibe in one little package, look at her:
package My::Names {
use MooseX::Extended types => [qw(compile Num NonEmptyStr Str PositiveInt ArrayRef)];
use List::Util 'sum';
# the distinction between `param` and `field` makes it easier to
# see which are available to `new`
param _name => ( isa => NonEmptyStr, init_arg => 'name' );
param title => ( isa => Str, required => 0 );
# forbidden in the constructor
field created => ( isa => PositiveInt, default => sub {time} );
sub name ($self) {
my $title = $self->title;
my $name = $self->_name;
return $title ? "$title $name" : $name;
}
sub add ( $self, $args ) {
state $check = compile( ArrayRef [ Num, 1 ] ); # at least one number
($args) = $check->($args);
return sum( $args->@* );
}
sub warnit ($self) {
carp("this is a warning");
}
}
likeβ¦ she's doing a lot. and she's doing it flawlessly π
π¦ DESCRIPTION π¦
okay so first thing first: this module is BETA code. It's feature-complete for release and has no known bugs. The author believes it's ready for production, but makes no promises. (their words, not mine, and honestly, respect for the honesty π)
This is just a quick overview, bestie. If you want the full meal, go see MooseX::Extended::Manual::Tutorial for more information.
So what is this class doing? It's attempting to create a safer version of Moose that defaults to read-only attributes, and it's easier to read and write. She's trying to bring some of the lessons learned from the Corinna project (https://github.com/Ovid/Cor), while acknowledging that you can't always get what you want β like true encapsulation and true methods. sad but real π
So this:
package My::Class {
use MooseX::Extended;
... your code here
}
is sort of the equivalent to this:
package My::Class {
use v5.20.0;
use Moose;
use MooseX::StrictConstructor;
use feature qw( signatures postderef postderef_qq );
no warnings qw( experimental::signatures experimental::postderef );
use namespace::autoclean;
use Carp;
use mro 'c3';
... your code here
__PACKAGE__->meta->make_immutable;
}
1;
see how much typing that saved?? iconic. it also exports two functions which are similar to Moose's has: param and field.
A param is a required parameter (defaults may be used). A field is not intended to be passed to the constructor. that's the whole distinction, that's the tea π
Note: thehasfunction is still available, even if it's not needed. Unlikeparamandfield, it still requires anisoption.
Also, while the author likes the postfix block syntax, it's not required. You can even safely inline multiple packages in the same file:
package My::Point;
use MooseX::Extended types => 'Num';
param [ 'x', 'y' ] => ( isa => Num );
package My::Point::Mutable;
use MooseX::Extended;
extends 'My::Point';
param [ '+x', '+y' ] => ( writer => 1, clearer => 1, default => 0 );
sub invert ($self) {
my ( $x, $y ) = ( $self->x, $self->y );
$self->set_x($y);
$self->set_y($x);
}
# MooseX::Extended will cause this to return true, even if we try to return
# false
0;
the last line returning 0 and still being true?? that's main character energy right there π
π CONFIGURATION π
You may pass an import list to MooseX::Extended. like so:
use MooseX::Extended
excludes => [qw/StrictConstructor carp/], # I don't want these features
types => [qw/compile PositiveInt HashRef/]; # I want these type tools
π types π
Allows you to import any types provided by MooseX::Extended::Types.
So this:
use MooseX::Extended::Role types => [qw/compile PositiveInt HashRef/];
Is identical to this:
use MooseX::Extended::Role;
use MooseX::Extended::Types qw( compile PositiveInt HashRef );
same thing, different font. periodt π
πΈ excludes πΈ
ngl, you might find some features annoying, or they might even cause potential bugs. For example, if you have a croak method, the importing of Carp::croak will be a problem. awkward π¬
A single argument to excludes can be a string. Multiple excludes require an array reference:
use MooseX::Extended excludes => [qw/StrictConstructor autoclean/];
Here's everything you can exclude, bestie:
StrictConstructor
use MooseX::Extended excludes => 'StrictConstructor';
Excluding this will no longer import MooseX::StrictConstructor.
autoclean
use MooseX::Extended excludes => 'autoclean';
Excluding this will no longer import namespace::autoclean.
c3
use MooseX::Extended excludes => 'c3';
Excluding this will no longer apply the C3 mro.
carp
use MooseX::Extended excludes => 'carp';
Excluding this will no longer import Carp::croak and Carp::carp.
immutable
use MooseX::Extended excludes => 'immutable';
Excluding this will no longer make your class immutable.
true
use MooseX::Extended excludes => 'true';
Excluding this will require your module to end in a true value.
param
use MooseX::Extended excludes => 'param';
Excluding this will make the param function unavailable.
field
use MooseX::Extended excludes => 'field';
Excluding this will make the field function unavailable.
π§ includes π§
Several optional features of MooseX::Extended make this module much more powerful. For example, to include try/catch and a method keyword:
use MooseX::Extended includes => [ 'method', 'try' ];
A single argument to includes can be a string. Multiple includes require an array reference:
use MooseX::Extended includes => [qw/method try/];
See MooseX::Extended::Manual::Includes for more information. π«Ά
π₯ REDUCING BOILERPLATE π₯
okay so let's say you've settled on the following feature set:
use MooseX::Extended
excludes => [qw/StrictConstructor carp/],
includes => 'method',
types => ':Standard';
And you keep typing that over and over. and over. and over. π We've removed a lot of boilerplate, bestie, but we've added different boilerplate. that's the catch fr fr. Instead, just create My::Custom::Moose and use My::Custom::Moose;. See MooseX::Extended::Custom for details. life hack unlocked β
π IMMUTABILITY π
π Making Your Class Immutable π
You no longer need to end your Moose classes with:
__PACKAGE__->meta->make_immutable;
That line prevents further changes to the class and provides some optimizations to make the code run much faster. but it's somewhat annoying to type, let's be real. We do this for you, via B::Hooks::AtRuntime. You no longer need to do this yourself. slay β¨
π¦ Making Your Instance Immutable π¦
By default, attributes defined via param and field are read-only. However β and this is the sneaky part β if they contain a reference, you can fetch the reference, mutate it, and now everyone with a copy of that reference has mutated state. shared trauma, but for data structures π
To handle that, we offer a new clone => $clone_type pair for attributes.
See the MooseX::Extended::Manual::Cloning documentation.
π OBJECT CONSTRUCTION π
Object construction for MooseX::Extended is identical to Moose, because MooseX::Extended is Moose, so no changes are needed. However, in addition to has, we also provide param and field attributes, and both of them are is => 'ro' by default. cute, right?
The param is required, whether by passing it to the constructor, or using default or builder.
The field is forbidden in the constructor and is lazy if it has a builder, because that builder is often dependent on attributes set in the constructor β and why call it if it's not used? exactly. efficiency queen π
Here's a short example:
package Class::Name {
use MooseX::Extended types => [qw(compile Num NonEmptyStr Str)];
# these default to 'ro' (but you can override that) and are required
param _name => ( isa => NonEmptyStr, init_arg => 'name' );
param title => ( isa => Str, required => 0 );
# fields must never be passed to the constructor
# note that ->title and ->name are guaranteed to be set before
# this because fields are lazy by default
field name => (
isa => NonEmptyStr,
default => sub ($self) {
my $title = $self->title;
my $name = $self->_name;
return $title ? "$title $name" : $name;
},
);
}
See MooseX::Extended::Manual::Construction for a full explanation.
π ATTRIBUTE SHORTCUTS π
When using field or param, we have some attribute shortcuts. here they are, look at her go:
param name => (
isa => NonEmptyStr,
writer => 1, # set_name
reader => 1, # get_name
predicate => 1, # has_name
clearer => 1, # clear_name
builder => 1, # _build_name
);
sub _build_name ($self) {
...
}
You can also do this:
param name ( isa => NonEmptyStr, builder => sub {...} );
That's the same as:
param name ( isa => NonEmptyStr, builder => '_build_name' );
sub _build_name {...}
See MooseX::Extended::Manual::Shortcuts for a full explanation.
π INVALID ATTRIBUTE DEFINITIONS π
okay so listen. The following Moose code will print WhoAmI. However, the second attribute name is clearly invalid. like, clearly. girl what is that name π
package Some::Class {
use Moose;
has name => ( is => 'ro' );
has '-bad' => ( is => 'ro' );
}
my $object = Some::Class->new( name => 'WhoAmI' );
say $object->name;
MooseX::Extended will throw a Moose::Exception::InvalidAttributeDefinition exception if it encounters an illegal method name for an attribute. it's not playing around, she said no β
This also applies to various attributes which allow method names, such as clone, builder, clearer, writer, reader, and predicate.
Trying to pass a defined init_arg to field will also throw this exception, unless the init_arg begins with an underscore. (It is sometimes useful to be able to define an init_arg for unit testing.) so the underscore is your hall pass π
π BUGS AND LIMITATIONS π
None known at this time. flawless behavior, honestly π§
πΈ MANUAL πΈ
the required reading, bestie. do your homework:
MooseX::Extended::Manual::TutorialMooseX::Extended::Manual::OverviewMooseX::Extended::Manual::ConstructionMooseX::Extended::Manual::IncludesMooseX::Extended::Manual::ShortcutsMooseX::Extended::Manual::Cloning
β RELATED MODULES β
MooseX::Extended::Typesis included in the distribution.
This provides core types for you. π
MooseX::Extended::Roleis included in the distribution.
MooseX::Extended, but for roles.
π± TODO π±
okay so bestie, real talk β some of this is literally just wishful thinking π and some of it would be so fun if other people wanted to collab. no pressure tho π«Ά
π§ Configurable Types
we give you MooseX::Extended::Types for convenience, plus the declare function. and we should write up (and test!!) examples of how to extend it. it's giving "planned" β¨
π BEGIN::Lift
this idea lowkey maybe belongs in MooseX::Extended::OverKill, butβ¦ π
quite often you see things like this:
BEGIN { extends 'Some::Parent' }
or this:
sub serial_number; # required by a role, must be compile-time
has serial_number => ( ... );
fr fr, there are a whole bunch of Moose functions that would work better if they ran at compile-time instead of runtime β it would make them look a touch more like native functions. my various attempts at solving this failed π but i confess i didn't try too hard. we move π
π NOTES π
there are a few things you might wanna know about this module when you're evaluating it π
most of this is written with bog-standard Moose, so there's nothing terribly weird inside, but you may wish to note that we use B::Hooks::AtRuntime and true. they seem sane, but caveat emptor β buyer beware, bestie π
π SEE ALSO π
- Corinna <https://github.com/Ovid/Cor> the RFC of the new version of OOP planned for the Perl core. π
- MooseX::Modern <https://metacpan.org/pod/MooseX::Modern> MooseX::Modern - Precision classes for Modern Perl β¨
- Zydeco <https://metacpan.org/pod/Zydeco> Zydeco - Jazz up your Perl π·
- Dios <https://metacpan.org/pod/Dios> Dios - Declarative Inside-Out Syntax π
- MooseX::AttributeShortcuts <https://metacpan.org/pod/MooseX::AttributeShortcuts> MooseX::AttributeShortcuts - Shorthand for common attribute options π
π AUTHOR π
Curtis "Ovid" Poe <curtis.poe@gmail.com>
π COPYRIGHT AND LICENSE π
This software is Copyright (c) 2022 by Curtis "Ovid" Poe.
This is free software, licensed under:
The Artistic License 2.0 (GPL Compatible)
and that's a wrap, bestie!! π«Ά this page is from perl v5.42.0, dated 2025-07-25, and it's the MooseX::Extended(3) manual page β go forth and write some iconic classes π
β¨
π¦ where this page comes from
- fedora 43: perl-MooseX-Extended 0.35-6.fc43 Β· Artistic-2.0
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms