Moose::...::Delta(3)

โœจ Moose::Manual::Delta โœจ

so this is the manual page Moose::...::Delta(3) โ€” it lives in the User Contributed Perl Documentation section of your friendly neighbourhood man pages, bestie ๐ŸŽ€


๐ŸŒธ NAME ๐ŸŒธ

Moose::Manual::Delta โ€” Important Changes in Moose ๐Ÿ’…


๐Ÿ’– VERSION ๐Ÿ’–

version 2.4000 โœจ


๐Ÿฆ‹ DESCRIPTION ๐Ÿฆ‹

okay so. this doc is the receipts ๐Ÿ“œ for every important / noteworthy change in Moose, with a big focus on the stuff that messes with backwards compatibility. yes it duplicates data from the Changes file, but it's giving more details and, when possible, workarounds. iykyk ๐Ÿ’…

and it's not just for keeping up โ€” you can also use this to find the lowest version of Moose that supported a given feature ๐Ÿ”. so if you hit a problem and you got a solution but it's not documented here, or you think we missed an important feature, please send us a patch ๐Ÿ™ we love that for us.


๐ŸŽ€ 2.1400 ๐ŸŽ€

Overloading implementation has changed ๐Ÿ”„

Overloading meta info used to be implemented by a Class::MOP::Method::Overload class. that class is gone ๐Ÿ’€ and overloading is now implemented by Class::MOP::Overload. the reasoning? overloading is not really equivalent to a method, so the old implementation didn't work properly for various cases. periodt.

all of the overloading-related methods for classes and roles have the same names, but those methods now return Class::MOP::Overload objects. โœจ

Core support for overloading in roles ๐Ÿ‘‘

Roles which use overloading now pass that overloading onto other classes (and roles) which consume that role. ๐Ÿซถ

this works much like MooseX::Role::WithOverloading, except that we properly detect overloading conflicts during role summation and when applying one role to another. MooseX::Role::WithOverloading did not do any conflict detection. nope. none. ๐Ÿ™ˆ

if you want to write code that uses overloading and works with previous versions of Moose and this one, upgrade to MooseX::Role::WithOverloading version 0.15 or greater. that version will detect when Moose itself handles overloading and get out of the way. iconic behaviour honestly ๐Ÿ’…


๐Ÿงš 2.1200 ๐Ÿงš

Classes created by Moose are now registered in %INC ๐Ÿ“‹

this means that this will no longer die (and will also no longer try to load Foo.pm):

{
    package Foo;
    use Moose;
}

# ...

use Foo;

if you're using the MOP, this behavior will occur when the create (or create_anon_class) method is used, but not when the initialize method is used. noted ๐Ÿ“

Moose now uses Module::Runtime instead of Class::Load to load classes ๐Ÿ“ฆ

Class::Load has always had some weird issues with the ways that it tries to figure out if a class is loaded. for instance, extending an empty package was previously impossible, because Class::Load would think that the class failed to load, even though that is a perfectly valid thing to do ๐Ÿ˜ญ. it was also difficult to deal with modules like IO::Handle, which partially populate several other packages when they are loaded (so calling load_class on 'IO::Handle' followed by 'IO::File' could end up with a broken IO::File, in some cases). yikes.

now, Moose uses the same mechanisms as perl itself to figure out if a class is loaded ๐Ÿช. a class is considered to be loaded if its entry in %INC is set. Perl sets the %INC entry for you automatically whenever a file is loaded via use or require. also, as mentioned above, Moose also now sets the %INC entry for any classes defined with it, even if they aren't loaded from a separate file. โœจ

this does however mean that if you are trying to use Moose with non-Moose classes defined in the same file, then you will need to set %INC manually now, where it may have worked in the past. for instance:

{
    package My::NonMoose;

    sub new { bless {}, shift }

    $INC{'My/NonMoose.pm'} = __FILE__;
    # alternatively:
    # use Module::Runtime 'module_notional_filename';
    # $INC{module_notional_filename(__PACKAGE__)} = __FILE__;
}

{
    package My::Moose;
    use Moose;

    extends 'My::NonMoose';
}

if you don't do this, you will get an error message about not being able to locate My::NonMoose in @INC. we hope that this case will be fairly rare. fingers crossed ๐Ÿคž

The Class::Load wrapper functions in Class::MOP have been deprecated ๐Ÿšซ

Class::MOP::load_class, Class::MOP::is_class_loaded, and Class::MOP::load_first_existing_class have been deprecated. they have been undocumented and discouraged since version 2.0200. you should replace their use with the corresponding functions in Class::Load, or just use Module::Runtime directly. do it bestie, your future self will thank you ๐Ÿ’–

The non-arrayref forms of enum and duck_type have been deprecated ๐Ÿšซ

originally, enum could be called like this:

enum('MyType' => qw(foo bar baz))

this was confusing, however (since it was different from the syntax for anonymous enum types), and it makes error checking more difficult (since you can't tell just by looking whether enum('Foo', 'Bar', 'Baz') was intended to be a type named Foo with elements of Bar and Baz, or if this was actually a mistake where someone got the syntax for an anonymous enum type wrong ๐Ÿ˜ต). this all also applies to duck_type.

calling enum and duck_type with a list of arguments as described above has been undocumented since version 0.93, and is now deprecated. you should replace

enum MyType => qw(foo bar baz);

in your code with

enum MyType => [qw(foo bar baz)];

square brackets, bestie. that's the whole glow-up โœจ

Moose string exceptions have been replaced by Moose exception objects ๐Ÿ’…

previously, Moose threw string exceptions on error conditions, which were not so verbose. all those string exceptions have now been converted to exception objects, which provide very detailed information about the exceptions. these exception objects provide a string overload that matches the previous exception message, so in most cases you should not have to change your code. phew ๐Ÿ˜ฎโ€๐Ÿ’จ

for learning about the usage of Moose exception objects, read Moose::Manual::Exceptions. individual exceptions are documented in Moose::Manual::Exceptions::Manifest. ๐Ÿ“š

this work was funded as part of the GNOME Outreach Program for Women. ๐Ÿซถ iconic, we love to see it.


โญ 2.1000 โญ

The Num type is now stricter ๐Ÿ”’

the Num type used to accept anything that fits Perl's notion of a number, which included Inf, NaN, and strings like " 1234 \n". we believe that the type constraint should indicate "this is a number", not "this coerces to a number". therefore, Num now only accepts integers, floating point numbers (both in decimal notation and exponential notation), 0, .0, 0.0, etc. no cap. ๐Ÿ’ฏ

if you want the old behavior you can use the LaxNum type in MooseX::Types::LaxNum.

You can use Specio instead of core Moose types ๐Ÿงช

the Specio distribution is an experimental new type system intended to eventually replace the core Moose types, but yet also work with things like Moo and Mouse and anything else. right now this is all speculative, but at least you can use Specio with Moose. โœจ


๐ŸŒˆ 2.0600 ๐ŸŒˆ

->init_meta is even less reliable at loading extensions ๐Ÿ˜ฌ

previously, calling MooseX::Foo->init_meta(@_) (and nothing else) from within your own init_meta had a decent chance of doing something useful. this was never supported behavior, and didn't always work anyway. due to some implementation adjustments, this now has a smaller chance of doing something useful, which could break code that was expecting it to continue doing useful things. code that does this should instead just call MooseX::Foo->import({ into => $into }). that's the move ๐Ÿ’…

All the Cookbook recipes have been renamed ๐Ÿ“–

we've given them all descriptive names, rather than numbers. this makes it easier to talk about them, and eliminates the need to renumber recipes in order to reorder them or delete one. no more "recipe #47 is now recipe #12" nonsense, we're free ๐Ÿฆ‹


๐Ÿ’œ 2.0400 ๐Ÿ’œ

The parent of a union type is its components' nearest common ancestor ๐Ÿ‘ช

previously, union types considered all of their component types their parent types. this was incorrect because parent types are defined as types that must be satisfied in order for the child type to be satisfied, but in a union, validating as any parent type will validate against the entire union. this has been changed to find the nearest common ancestor for all of its components. for example, a union of Int|ArrayRef[Int] now has a parent of Defined. ๐Ÿ“Œ

Union types consider all members in the is_subtype_of and is_a_type_of methods ๐Ÿ”

previously, a union type would report itself as being of a subtype of a type if any of its member types were subtypes of that type. this was incorrect because any value that passes a subtype constraint must also pass a parent constraint. this has changed so that all of its member types must be a subtype of the specified type. all of them. every single one. periodt ๐Ÿ’…

Enum types now work with just one value 1๏ธโƒฃ

previously, an enum type needed to have two or more values. nobody knew why, so we fixed it. that's it. that's the change. ๐Ÿ˜Œ

Methods defined in UNIVERSAL now appear in the MOP ๐ŸŒŒ

any method introspection methods that look at methods from parent classes now find methods defined in UNIVERSAL. this includes methods like $class->get_all_methods and $class->find_method_by_name. ๐Ÿ‘‘

this also means that you can now apply method modifiers to these methods. ๐Ÿ”ฅ

Hand-optimized type constraint code causes a deprecation warning ๐Ÿšซ

if you provide an optimized sub ref for a type constraint, this now causes a deprecation warning. typically, this comes from passing an optimize_as parameter to subtype, but it could also happen if you create a Moose::Meta::TypeConstraint object directly.

use the inlining feature (inline_as) added in 2.0100 instead. ๐Ÿ’ก

Class::Load::load_class and is_class_loaded have been removed ๐Ÿ’€

the Class::MOP::load_class and Class::MOP::is_class_loaded subroutines are no longer documented, and will cause a deprecation warning in the future. Moose now uses Class::Load to provide this functionality, and you should do so as well. ๐Ÿซถ


๐Ÿ“ 2.0205 ๐Ÿ“

Array and Hash native traits provide a shallow_clone method ๐Ÿชž

the Array and Hash native traits now provide a shallow_clone method, which will return a reference to a new container with the same contents as the attribute's reference. cute, right? ๐ŸŽ€

2.0200

โœจ Hand-optimized type constraint code is deprecated in favor of inlining โœจ

okay so bestie, Moose used to let you hand in a hand-optimized version of a type constraint's subroutine reference. Cute, but the glow-up is that type constraints can now generate inline code โ€” and you should be using that inlining instead of handing over a hand-optimized sub ref. ๐Ÿ’…

This hits the optimize_as sub that Moose::Util::TypeConstraints exports. Use inline_as instead, queen.

heads up: this will start warning in the 2.0300 release. so like, get ahead of it. ๐Ÿ™ˆ

2.0002

๐Ÿซถ More useful type constraint error messages ๐Ÿซถ

if you've got Devel::PartialDump version 0.14 or higher installed, Moose's type constraint error messages will use it to actually show you the invalid value instead of just dumping it raw. it's giving way more useful, no cap. so instead of this sad little thing:

Attribute (foo) does not pass the type constraint because: Validation failed for 'ArrayRef[Int]' with value ARRAY(0x275eed8)

the error message will instead look like

Attribute (foo) does not pass the type constraint because: Validation failed for 'ArrayRef[Int]' with value [ "a" ]
ngl, Devel::PartialDump can't be made a direct dependency at the moment because it uses Moose itself ๐Ÿ˜ญ, but the team is considering options to make this easier. we love a self-referential icon.

2.0000

๐Ÿ‘‘ Roles have their own default attribute metaclass ๐Ÿ‘‘

previously, when a role got applied to a class, it would use the attribute metaclass defined in the class when copying over the attributes from the role. and that was, lowkey, wrong โ€” because for instance, using MooseX::FollowPBP in the class would end up renaming all of the accessors generated by the role, some of which may be being called inside the role, causing it to break. ๐Ÿ’€

Roles now keep track of their own attribute metaclass to use by default when being applied to a class (defaulting to Moose::Meta::Attribute). this is modifiable using Moose::Util::MetaRole by passing the applied_attribute key to the role_metaroles option, as in:

Moose::Util::MetaRole::apply_metaroles(
    for => __PACKAGE__,
    class_metaroles => {
        attribute => ['My::Meta::Role::Attribute'],
    },
    role_metaroles => {
        applied_attribute => ['My::Meta::Role::Attribute'],
    },
);

๐ŸŒˆ Class::MOP has been folded into the Moose dist ๐ŸŒˆ

Moose and Class::MOP are tightly related enough that they've always had to be kept pretty closely in step in terms of versions. making them into a single dist should simplify the upgrade process for users, since it should no longer be possible to upgrade one without the other and potentially cause issues. no functionality has changed, and this should be entirely transparent. โœจ

๐Ÿ”ฅ Moose's conflict checking is more robust and useful ๐Ÿ”ฅ

there are two parts to this. the most useful one right now is that Moose will ship with a moose-outdated script, which can be run at any point to list the modules which are installed that conflict with the installed version of Moose. after upgrading Moose, running moose-outdated | cpanm should be sufficient to ensure that all of the Moose extensions you use will continue to work. ๐Ÿซถ

the other part is that Moose's META.json file will also specify the conflicts under the x_conflicts (now x_breaks) key. we are working with the Perl tool chain developers to try to get conflicts support added to CPAN clients, and if/when that happens, the metadata already exists, and so the conflict checking will become automatic. iconic behaviour tbh.

๐Ÿ’œ The lazy_build attribute feature is discouraged ๐Ÿ’œ

while not deprecated, we strongly discourage you from using this feature.

โญ Most deprecated APIs/features are slated for removal in Moose 2.0200 โญ

most of the deprecated APIs and features in Moose will start throwing an error in Moose 2.0200. some of the features will go away entirely, and some will simply throw an error.

the things on the chopping block are:

  • Old public methods in Class::MOP and Moose

this includes things like Class::MOP::Class->get_attribute_map, Class::MOP::Class->construct_instance, and many others. these were deprecated in Class::MOP 0.80_01, released on April 5, 2009.

these methods will be removed entirely in Moose 2.0200. ๐Ÿ˜ญ

  • Old public functions in Class::MOP

this includes Class::MOP::subname, Class::MOP::in_global_destruction, and the Class::MOP::HAS_ISAREV constant. the first two were deprecated in 0.84, and the last in 0.80. Class::MOP 0.84 was released on May 12, 2009.

these functions will be removed entirely in Moose 2.0200.

  • The alias and excludes option for role composition

these were renamed to -alias and -excludes in Moose 0.89, released on August 13, 2009.

passing these will throw an error in Moose 2.0200.

  • The old Moose::Util::MetaRole API

this includes the apply_metaclass_roles() function, as well as passing the for_class or any key ending in _roles to apply_metaroles(). this was deprecated in Moose 0.93_01, released on January 4, 2010.

these will all throw an error in Moose 2.0200.

  • Passing plain lists to type() or subtype()

the old API for these functions allowed you to pass a plain list of parameters, rather than a list of hash references (which is what as(), where, etc. return). this was deprecated in Moose 0.71_01, released on February 22, 2009.

this will throw an error in Moose 2.0200.

  • The Role subtype

this subtype was deprecated in Moose 0.84, released on June 26, 2009.

this will be removed entirely in Moose 2.0200. ๐Ÿชฆ


1.21

  • New release policy

as of the 2.0 release, Moose now has an official release and support policy, documented in Moose::Manual::Support. all API changes will now go through a deprecation cycle of at least one year, after which the deprecated API can be removed. deprecations and removals will only happen in major releases.

in between major releases, we will still make minor releases to add new features, fix bugs, update documentation, etc. balance, bestie. โš–๏ธ


1.16

๐ŸŒธ Configurable stacktraces ๐ŸŒธ

classes which use the Moose::Error::Default error class can now have stacktraces disabled by setting the MOOSE_ERROR_STYLE env var to croak. this is experimental, fairly incomplete, and won't work in all cases (because Moose's error system in general is all of these things ๐Ÿ™ˆ), but this should allow for reducing at least some of the verbosity in most cases.


1.15

๐Ÿฆ‹ Native Delegations ๐Ÿฆ‹

in previous versions of Moose, the Native delegations were created as closures. the generated code was often quite slow compared to doing the same thing by hand. for example, the Array's push delegation ended up doing something like this:

push @{ $self->$reader() }, @_;

if the attribute was created without a reader, the $reader sub reference followed a very slow code path. even with a reader, this is still slower than it needs to be. ๐Ÿ’€

Native delegations are now generated as inline code, just like other accessors, so we can access the slot directly. slay.

in addition, native traits now do proper constraint checking in all cases. in particular, constraint checking has been improved for array and hash references. previously, only the contained type (the Str in HashRef[Str]) would be checked when a new value was added to the collection. however, if there was a constraint that applied to the whole value, this was never checked. ๐Ÿ˜ฑ

in addition, coercions are now called on the whole value.

the delegation methods now do more argument checking. all of the methods check that a valid number of arguments were passed to the method. in addition, the delegation methods check that the arguments are sane (array indexes, hash keys, numbers, etc.) when applicable. we have tried to emulate the behavior of Perl builtins as much as possible. ๐Ÿ’…

finally, triggers are called whenever the value of the attribute is changed by a Native delegation.

these changes are only likely to break code in a few cases.

  • the inlining code may or may not preserve the original reference when changes are made. in some cases, methods which change the value may replace it entirely. this will break tied values. ๐Ÿ˜ญ
  • if you have a typed arrayref or hashref attribute where the type enforces a constraint on the whole collection, this constraint will now be checked. it's possible that code which previously ran without errors will now cause the constraint to fail. however, presumably this is a good thing ;)
  • if you are passing invalid arguments to a delegation which were previously being ignored, these calls will now fail.
  • if your code relied on the trigger only being called for a regular writer, that may cause problems.
as always, you are encouraged to test before deploying the latest version of Moose to production. fr fr, don't skip this one. ๐Ÿซถ

๐ŸŽ€ Defaults is and default for String, Counter, and Bool ๐ŸŽ€

a few native traits (String, Counter, Bool) provide default values of is and default when you created an attribute. allowing them to provide these values is now deprecated. supply the value yourself when creating the attribute, bestie.

๐Ÿ’… The meta method ๐Ÿ’…

Moose and Class::MOP have been cleaned up internally enough to make the meta method that you get by default optional. use Moose and use Moose::Role now can take an additional -meta_name option, which tells Moose what name to use when installing the meta method. passing undef to this option suppresses generation of the meta method entirely. this should be useful for users of modules which also use a meta method or function, such as Curses or Rose::DB::Object. โœจ

1.09 ๐ŸŽ€

All deprecated features now warn

Okay so back in the day, "deprecation" basically meant somebody typed "X is deprecated" in the Changes file and then we all justโ€ฆ moved on? ๐Ÿ’€ We were not consistent about actually warning anybody. Now? Every deprecated feature still hanging out in Moose actually gives you a warning. And it's issued once per calling package, so your terminal doesn't get absolutely flooded. Peep Moose::Deprecated for the deets.

You cannot pass coerce => 1 unless the attribute's type constraint has a coercion

Bestie. Previously this was justโ€ฆ accepted? And it sort of worked, except the moment you tried to set that attribute after the object already existed, you'd get a runtime error. Rude.

Now you get a warning right when you try to define the attribute. Much better, lowkey. โœจ

no Moose, no Moose::Role, and no Moose::Exporter no longer unimport strict and warnings

So this got changed in 1.05, and now it's been reverted. Why? Because we have no idea if you explicitly loaded strict or warnings yourself, and unimporting them in that case is just broken. Periodt.

Reversed logic when defining which options can be changed

Moose::Meta::Attribute now lets you change all the options in an overridden attribute. The old way made you whitelist every single option using the legal_options_for_inheritance method. That method is gone, and there's a new one in town: illegal_options_for_inheritance, which you use to prevent certain options from being changeable. ๐Ÿ’…

Also โ€” and this is the slay part โ€” we only throw an error if the illegal option is actually changed. If the superclass never specified that option at all when defining the attribute, the subclass version can still add it as an option. Flexible, iconic.

Example of overriding this in an attribute trait:

package Bar::Meta::Attribute;
use Moose::Role;

has 'my_illegal_option' => (
    isa => 'CodeRef',
    is  => 'rw',
);

around illegal_options_for_inheritance => sub {
    return ( shift->(@_), qw/my_illegal_option/ );
};

1.05 ๐Ÿฆ‹

"BUILD" in Moose::Object methods are now called when calling "new_object"

Before, BUILD methods only got called from Moose::Object::new. But now they also fire when you construct an object through Moose::Meta::Class::new_object. Like, BUILD methods are an inherent part of object construction, so this makes $meta->new_object actually usable without forcing everyone to go through $meta->name->new. No cap. ๐Ÿซถ

no Moose, no Moose::Role, and no Moose::Exporter now unimport strict and warnings

The whole vibe here was: if use Moose does a thing in your calling scope, then no Moose should clean it all up. So no Moose โ€” plus every other module that uses Moose::Exporter โ€” now unimports strict and warnings.

Yeah bestie, this is the one that got reverted in 1.09. Keep reading, it's fine. ๐Ÿ˜ญ

Metaclass compatibility checking and fixing should be much more robust

The metaclass compatibility checking AND fixing algorithms got completely rewritten, in both Class::MOP and Moose. This should squash a whole bunch of confusing errors you'd hit with non-Moose inheritance and custom metaclasses for things like attributes, constructors, etc.

For correct code, the only thing you'd need to change is that custom error metaclasses must now inherit from Moose::Error::Default. That's it. Slay. โœจ


1.02 ๐ŸŒธ

Moose::Meta::TypeConstraint::Class is_subtype_of behavior

Earlier versions of is_subtype_of would incorrectly return true when called with itself, its own TC name, or its class name as an argument. Like, $foo_tc->is_subtype_of('Foo') == 1? Ma'am. ๐Ÿ™ˆ

That happened because isa was being checked before the class name. If you still want the old behavior, you can get at it with is_type_of.


1.00 ๐Ÿ’œ

Moose::Meta::Attribute::Native::Trait::Code no longer creates reader methods by default

Earlier versions of Moose::Meta::Attribute::Native::Trait::Code were out here creating read-only accessors for the attributes it got applied toโ€ฆ even if you never asked for it with is => 'ro'. Incorrect behavior, bestie. Fixed now. โœจ


0.95 โญ

Moose::Util add_method_modifier behavior

add_method_modifier โ€” and by extension the sugar functions Moose::before, Moose::after, and Moose::around โ€” can now accept arrayrefs, with the same behavior as lists. Anything that isn't an arrayref or a regexp results in an error. Simple as that. ๐Ÿ’…


0.93_01 and 0.94 ๐Ÿงš

Moose::Util::MetaRole API has changed

The apply_metaclass_roles function is now called apply_metaroles. And the way you supply arguments changed too โ€” specifically to force you to distinguish between metaroles applied to Moose::Meta::Class (and helpers) versus Moose::Meta::Role.

The old API still works, but it'll warn in a future release, and eventually get removed. So maybe migrate, bestie? ๐Ÿ‘‘

Moose::Meta::Role has real attributes

The attributes returned by Moose::Meta::Role are now instances of the Moose::Meta::Role::Attribute class, instead of bare hash references. Glow up fr fr. โœจ

no Moose now removes blessed and confess

Moose is now smart enough to know exactly what it exported โ€” even when it re-exports functions from other packages. So when you no Moose, it'll remove these functions from your namespaceโ€ฆ unless you also imported them directly from their respective packages.

Heads up: if you've got a no Moose sitting in your code before you call blessed or confess, your code will break. ๐Ÿ’€

You've got two options: move the no Moose call later in your code, or explicitly import the relevant functions from the packages that provide them. Pick your fighter. ๐Ÿซถ

Moose::Exporter is smarter about unimporting re-exports

That change above comes from a general improvement to Moose::Exporter. It will now unimport any function it exports โ€” even if that function is a re-export from another package. Iconic behavior. ๐Ÿ’…

Attributes in roles can no longer override class attributes with +foo

Previously this worked more or less accidentally, because role attributes weren't objects yet. It was never documented, but a few MooseX modules were out here taking advantage of it. No more, bestie. ๐Ÿšซ

The composition_class_roles attribute in Moose::Meta::Role is now a method

This got done so that roles can alter the list of composition class roles by applying a method modifier. Before, it was an attribute and MooseX modules would override it โ€” and since that no longer works, it became a method.

Fun little note: this should be an attribute, so it may switch back to being an attribute in the future if we figure out how to make it work. Keeping it real. ๐Ÿ™ˆ


0.93 ๐ŸŽ€

Calling $object->new() is no longer deprecated

We decided to undeprecate this. Now it just works. โœจ

Both get_method_map and get_attribute_map is deprecated

These metaclass methods were never meant to be public, and now they're both deprecated. The workaround, if you still need what they did, is to iterate over the list of names manually:

my %fields = map { $_ => $meta->get_attribute($_) } $meta->get_attribute_list;

Technically this was a change in Class::MOP, but this version of Moose requires a version of Class::MOP that includes said change. So. Yeah. ๐Ÿ’…


0.90 ๐Ÿฆ‹

Added Native delegation for Code refs

See Moose::Meta::Attribute::Native::Trait::Code for the details, bestie.

Calling $object->new() is deprecated

Moose has supported this forever, but it was never really documented, and ngl we don't think it's good practice. If you want to construct an object from an existing object, provide some kind of alternate constructor, like $object->clone. ๐Ÿซถ

Calling $object->new now issues a warning, and will be an error in a future release.

Moose no longer warns if you call make_immutable for a class with mutable ancestors

In theory this is a good thing to warn about. In practice? We found so many exceptions to it that doing it properly became quite problematic. So we stopped. ๐Ÿ˜ญ


0.89_02 โญ

New Native delegation methods from List::Util and List::MoreUtils

Specifically, we now have reduce, shuffle, uniq, and natatime. Go off. ๐Ÿ”ฅ

The Moose::Exporter with_caller feature is now deprecated

Use with_meta instead. The with_caller option will start warning in a future release.

Moose now warns if you call make_immutable for a class with mutable ancestors

Okay this one is actually important, listen up. This is dangerous because modifying a class after a subclass has been immutabilized leads to incorrect results in that subclass โ€” due to inlining, caching, etc.

This occasionally happens by accident, when a class loads one of its subclasses right in the middle of its own class definition. So pointing out that this may cause issues should be genuinely helpful.

Metaclasses โ€” that's classes that inherit from Class::MOP::Object โ€” are currently exempt from this check, since at the moment we aren't very consistent about which metaclasses we immutabilize. ๐Ÿ™ˆ

enum and duck_type now take arrayrefs for all forms

Previously, calling these functions with a list would take the first element of the list as the type constraint name, and use the remainder as the enum values or method names. That makes the interface inconsistent with the anon-type forms of these functions (which must take an arrayref), and a free-form list where the first value is sometimes special is hard to validate โ€” and even harder to give reasonable error messages for. ๐Ÿ˜ญ

So these functions have been changed to take arrayrefs in all their forms. Meaning enum 'My::Type' => [qw(foo bar)] is now the preferred way to create an enum type constraint. The old syntax still works for now, but hopefully it'll get deprecated and removed in a future release. โœจ

0.89_01 ๐Ÿซถ

okay bestie, big glow-up energy here: Moose::Meta::Attribute::Native got scooped up out of MooseX::AttributeHelpers and moved right into the Moose core itself. and the major changes? absolutely iconic, let's go:

"traits", not "metaclass" โœจ

method providers are only available via traits now. periodt.

"handles", not "provides" or "curries" ๐Ÿ’…

the provides syntax was giving core Moose handles => HASHREF syntax but with the keys and values flipped around, which was lowkey so confusing. so AttributeHelpers now uses handles => HASHREF in a way that should feel intuitive to anyone already familiar with how it's used for other attributes. ๐ŸŽ€

the curries functionality that AttributeHelpers provided has been generalized to apply to all cases of handles => HASHREF, though not every piece of functionality has been ported โ€” specifically, currying with a CODEREF is not supported. ๐Ÿ˜ญ

"empty" is now "is_empty", and means empty, not non-empty ๐Ÿ’€

previously, the empty method provided by Arrays and Hashes returned true if the attribute was not empty (no elements). now it returns true if the attribute is empty. it was also renamed to is_empty, to reflect this. yes bestie, the old one was literally lying to you.

"find" was renamed to "first", and "first" and "last" were removed ๐ŸŒธ

List::Util refers to the functionality that we used to provide under find as first, so that will likely be more familiar (and will fit in better if we decide to add more List::Util functions). first and last were removed, since their functionality is easily duplicated with curries of get.

Helpers that take a coderef of one argument now use $_ ๐Ÿงš

Subroutines passed as the first argument to first, map, and grep now receive their argument in $_ rather than as a parameter to the subroutine. Helpers that take a coderef of two or more arguments remain using the argument list (there are technical limitations to using $a and $b like sort does).

See Moose::Meta::Attribute::Native for the new documentation.

the alias and excludes role parameters got renamed ๐Ÿ‘‘

The alias and excludes role parameters have been renamed to -alias and -excludes. The old names still work, but new code should use the new names, and eventually the old ones will be deprecated and removed.


0.89 ๐ŸŒˆ

use Moose -metaclass => 'Foo' now does alias resolution, just like -traits (and the metaclass and traits options to has).

Added two functions meta_class_alias and meta_attribute_alias to Moose::Util, to simplify aliasing metaclasses and metatraits. This is a wrapper around the old

package Moose::Meta::Class::Custom::Trait::FooTrait;
sub register_implementation { 'My::Meta::Trait' }

way of doing this.


0.84 ๐ŸŽ€

When an attribute generates no accessors, we now warn. This is to help users who forget the is option. If you really do not want any accessors, you can use is => 'bare'. You can maintain back compat with older versions of Moose by using something like:

($Moose::VERSION >= 0.84 ? is => 'bare' : ())

When an accessor overwrites an existing method, we now warn. To work around this warning (if you really must have this behavior), you can explicitly remove the method before creating it as an accessor:

sub foo {}

__PACKAGE__->meta->remove_method('foo');

has foo => (
    is => 'ro',
);

When an unknown option is passed to has, we now warn. You can silence the warning by fixing your code. :) ๐Ÿ’–

The Role type has been deprecated. On its own, it was useless, since it just checked $object->can('does'). If you were using it as a parent type, just call role_type('Role::Name') to create an appropriate type instead.


0.78 ๐Ÿฆ‹

use Moose::Exporter; now imports strict and warnings into packages that use it.


0.77 โญ

DEMOLISHALL and DEMOLISH now receive an argument indicating whether or not we are in global destruction.


0.76 ๐Ÿ’œ

Type constraints no longer run coercions for a value that already matches the constraint. This may affect some (arguably buggy) edge case coercions that rely on side effects in the via clause.


0.75 ๐ŸŒธ

Moose::Exporter now accepts the -metaclass option for easily overriding the metaclass (without metaclass). This works for classes and roles.


0.74 ๐Ÿ“

Added a duck_type sugar function to Moose::Util::TypeConstraints to make integration with non-Moose classes easier. It simply checks if $obj->can() a list of methods.

A number of methods (mostly inherited from Class::MOP) have been renamed with a leading underscore to indicate their internal-ness. The old method names will still work for a while, but will warn that the method has been renamed. In a few cases, the method will be removed entirely in the future. This may affect MooseX authors who were using these methods. ๐Ÿ˜ญ


0.73 ๐Ÿ”ฅ

Calling subtype with a name as the only argument now throws an exception. If you want an anonymous subtype do:

my $subtype = subtype as 'Foo';

This is related to the changes in version 0.71_01.

The is_needed method in Moose::Meta::Method::Destructor is now only usable as a class method. Previously, it worked as a class or object method, with a different internal implementation for each version.

The internals of making a class immutable changed a lot in Class::MOP 0.78_02, and Moose's internals have changed along with it. The external $metaclass->make_immutable method still works the same way.


0.72 ๐Ÿ’…

A mutable class accepted Foo->new(undef) without complaint, while an immutable class would blow up with an unhelpful error. Now, in both cases we throw a helpful error instead.

This "feature" was originally added to allow for cases such as this:

my $args;

if ( something() ) {
    $args = {...};
}

return My::Class->new($args);

But we decided this is a bad idea and a little too magical, because it can easily mask real errors. ๐Ÿ’€


0.71_01 โœจ

Calling type or subtype without the sugar helpers (as, where, message) is now deprecated.

As a side effect, this meant we ended up using Perl prototypes on as, and code like this will no longer work:

use Moose::Util::TypeConstraints;
use Declare::Constraints::Simple -All;

subtype 'ArrayOfInts'
    => as 'ArrayRef'
    => IsArrayRef(IsInt);

Instead it must be changed to this:

subtype(
    'ArrayOfInts' => {
        as    => 'ArrayRef',
        where => IsArrayRef(IsInt)
    }
);

If you want to maintain backwards compat with older versions of Moose, you must explicitly test Moose's VERSION:

if ( Moose->VERSION < 0.71_01 ) {
    subtype 'ArrayOfInts'
        => as 'ArrayRef'
        => IsArrayRef(IsInt);
}
else {
    subtype(
        'ArrayOfInts' => {
            as    => 'ArrayRef',
            where => IsArrayRef(IsInt)
        }
    );
}

0.70 ๐Ÿงš

We no longer pass the meta-attribute object as a final argument to triggers. This actually changed for inlined code a while back, but the non-inlined version and the docs were still out of date.

If by some chance you actually used this feature, the workaround is simple. You fetch the attribute object from out of the $self that is passed as the first argument to trigger, like so:

has 'foo' => (
    is      => 'ro',
    isa     => 'Any',
    trigger => sub {
        my ( $self, $value ) = @_;
        my $attr = $self->meta->find_attribute_by_name('foo');

        # ...
    }
);

0.66 ๐ŸŒˆ

If you created a subtype and passed a parent that Moose didn't know about, it simply ignored the parent. Now it automatically creates the parent as a class type. This may not be what you want, but is less broken than before.

You could declare a name with subtype such as Foo!Bar. Moose would accept this allowed, but if you used it in a parameterized type such as ArrayRef[Foo!Bar] it wouldn't work. We now do some vetting on names created via the sugar functions, so that they can only contain alphanumerics, :, and ..


0.65 ๐Ÿ‘‘

Methods created via an attribute can now fulfill a requires declaration for a role. Honestly we don't know why Stevan didn't make this work originally, he was just insane or something. ๐Ÿ˜ญ

Stack traces from inlined code will now report the line and file as being in your class, as opposed to in Moose guts.


0.62_02 ๐Ÿ’–

When a class does not provide all of a role's required methods, the error thrown now mentions all of the missing methods, as opposed to just the first missing method.

Moose will no longer inline a constructor for your class unless it inherits its constructor from Moose::Object, and will warn when it doesn't inline. If you want to force inlining anyway, pass replace_constructor => 1 to make_immutable.

If you want to get rid of the warning, pass inline_constructor => 0.


0.62 ๐Ÿฆ‹

Removed the (deprecated) make_immutable keyword.

Removing an attribute from a class now also removes delegation (handles) methods installed for that attribute. This is correct behavior, but if you were wrongly relying on it you might get bit.


0.58 โญ

Roles now add methods by calling add_method, not alias_method. They make sure to always provide a method object, which will be cloned internally. This means that it is now possible to track the source of a method provided by a role, and even follow its history through intermediate roles. This means that methods added by a role now show up when looking at a class's method list/map.

Parameter and Union args are now sorted, this makes Int|Str the same constraint as Str|Int. Also, incoming type constraint strings are normalized to remove all whitespace differences. This is mostly for internals and should not affect outside code.

Moose::Exporter will no longer remove a subroutine that the exporting package re-exports. Moose re-exports the Carp::confess function, among others. The reasoning is that we cannot know whether you have also explicitly imported those functions for your own use, so we err on the safe side and always keep them.


0.56 ๐ŸŒธ

Moose::init_meta should now be called as a method.

New modules for extension writers, Moose::Exporter and Moose::Util::MetaRole.


0.55_01 ๐Ÿ’œ

Implemented metaclass traits (and wrote a recipe for it):

use Moose -traits => 'Foo'

This should make writing small Moose extensions a little easier.


0.55 ๐ŸŽ€

Fixed coerce to accept anon types just like subtype can. So that you can do:

coerce $some_anon_type => from 'Str' => via { ... };

0.51 โœจ

Added BUILDARGS, a new step in Moose::Object->new().

0.49 โœจ

Okay so bestie, they fixed how is => (ro|rw) works with your custom-defined reader, writer, and accessor options. The way it lands now? Peep the little table below, it's giving clarity:

is => ro, writer => _foo    # turns into (reader => foo, writer => _foo)
is => rw, writer => _foo    # turns into (reader => foo, writer => _foo)
is => rw, accessor => _foo  # turns into (accessor => _foo)
is => ro, accessor => _foo  # error, accesor is rw

0.45 ๐ŸŒธ

The before/around/after method modifiers now support regexp matching of method names. NOTE: this only works for classes, it is currently not supported in roles, but, ... patches welcome. ๐Ÿ‘€

The has keyword for roles now accepts the same array ref form that Moose.pm does for classes.

A trigger on a read-only attribute is no longer an error, as it's useful to trigger off of the constructor.

Subtypes of parameterizable types now are parameterizable types themselves.


0.44 ๐Ÿ’€

Fixed issue where DEMOLISHALL was eating the value in $@, and so not working correctly. It still kind of eats them, but so does vanilla perl.


0.41 ๐Ÿฆ‹

Inherited attributes may now be extended without restriction on the type ('isa', 'does').

The entire set of Moose::Meta::TypeConstraint::* classes were refactored in this release. If you were relying on their internals you should test your code carefully.


0.40 ๐ŸŽ€

Documenting the use of '+name' with attributes that come from recently composed roles. It makes sense, people are using it, and so why not just officially support it.

The Moose::Meta::Class->create method now supports roles.

It is now possible to make anonymous enum types by passing "enum" an array reference instead of the "enum $name => @values".


0.37 ๐Ÿ”ฅ

Added the make_immutable keyword as a shortcut to calling make_immutable on the meta object. This eventually got removed! ๐Ÿ˜ญ

Made init_arg => undef work in Moose. This means "do not accept a constructor parameter for this attribute".

Type errors now use the provided message. Prior to this release they didn't.


0.34 ๐Ÿ‘‘

Moose is now a postmodern object system :)

The Role system was completely refactored. It is 100% backwards compat, but the internals were totally changed. If you relied on the internals then you are advised to test carefully.

Added method exclusion and aliasing for Roles in this release.

Added the Moose::Util::TypeConstraints::OptimizedConstraints module.

Passing a list of values to an accessor (which is only expecting one value) used to be silently ignored, now it throws an error.


0.26 ๐ŸŒˆ

Added parameterized types and did a pretty heavy refactoring of the type constraint system.

Better framework extensibility and better support for "making your own Moose".


0.25 or before ๐Ÿ’…

Honestly, you shouldn't be using versions of Moose that are this old, so many bug fixes and speed improvements have been made you would be crazy to not upgrade.

Also, I am tired of going through the Changelog so I am stopping here, if anyone would like to continue this please feel free.


AUTHORS ๐Ÿ‘‘๐Ÿ’–

  • Stevan Little <stevan@cpan.org>
  • Dave Rolsky <autarch@urth.org>
  • Jesse Luehrs <doy@cpan.org>
  • Shawn S Moore <sartak@cpan.org>
  • ื™ื•ื‘ืœ ืงื•ื’'ืžืŸ (Yuval Kogman) <nothingmuch@woobling.org>
  • Karen Etheridge <ether@cpan.org>
  • Florian Ragwitz <rafl@debian.org>
  • Hans Dieter Pearcey <hdp@cpan.org>
  • Chris Prather <chris@prather.org>
  • Matt S Trout <mstrout@cpan.org>

This software is copyright (c) 2006 by Infinity Interactive, Inc.

This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself.


And that's a wrap on Moose::...::Delta(3), bestie! This was perl v5.42.0, dated 2025-07-25. Now go make your code iconic, periodt. ๐Ÿ’…โœจ๐Ÿฆ‹

๐Ÿ“ฆ where this page comes from