Hello Monks!

I'm back with another Moose question. Fortunately, this one's easy to lay out.

I have the following code:

package Point; use Moose; use namespace::autoclean; has 'x' => ( isa => 'Int', is => 'rw', required => 1 ); has 'y' => ( isa => 'Int', is => 'rw', required => 1 ); package Named; use Moose::Role; use namespace::autoclean; has 'name' => ( isa => 'Str', is => 'rw', required => 1 ); package main; use Moose::Util; my $p = Point->new( x => 1, y => 1 ); my $role = 'Named'; $role->meta->apply( $p ); # <-- line 41 print $p->dump;

This code fails with the following:

Attribute (name) is required at /nfs/pdx/disks/nehalem.pde.077/perl/5. +12.2/lib64/site_perl/x86_64-linux/Moose/Meta/Attribute.pm line 514 ...<snipping unnecessary trace info>.. Moose::Meta::Role::apply('Moose::Meta::Role=HASH(0x114b110)', 'Moose:: +Meta::Class::__ANON__::SERIAL::1=HASH(0xfc2748)') called at /nfs/pdx/ +disks/nehalem.pde.077/scripts/test3.pl line 41

The problem is that the 'name' attribute in the Named role is required. However, I've already created my Point instance before I compose the Named role into this. This problem goes away if you remove the required parameter from the 'name' attribute in the Named role.

Obviously, there are many workarounds to this issue. Disabling the required parameter and initializing the attribute after role application is one. Ensuring the attribute is already defined by the instance is another. Composing the role into the class prior to instantiation is a third.

I believe having to remove the required parameter from the attribute and relying on the programmer to remember to properly initialize the attribute is the wrong way to do this. Moose provides the required parameter explicitly to ensure that a given attribute is properly initialized. Ensuring the instance already has an attribute that satisfies the requirement seems to be a convoluted way to solve the issue, definitely worse than the first workaround. Composing the role into the class prior to instantiation limits flexibility as I am trying to apply differing roles to differing instances.

So, the summary: Is there a good way to compose a role with a required attribute into an instance other than what I've outlined above?

Thanks in advance for taking the time to read my question, it is always appreciated!


In reply to Moose composing role with required attribute into existing instance by tj_thompson

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.