3

I am trying to coerce from the type ArrayRef[HashRef] to ArrayRef[MyModule::Object], but for some reason I am getting an error. Below is my type constraint class:

package MyModule::Types;
use Mouse::Util::TypeConstraints;

subtype 'CoercedArrayRefOfMyModuleObjects' => as 'ArrayRef[MyModule::Object]';
coerce 'CoercedArrayRefOfMyModuleObjects'
    => from 'ArrayRef[HashRef]'
    => via { [map { MyModule::Object->new( %{$_} ) } @{$_}] };

no Mouse::Util::TypeConstraints;
1;

And this is the class that has an array ref of MyModule::Objects:

use strict;
package MyModule;
use Mouse;
use MyModule::Types;

has objects => ( 
    is => 'rw',
    isa => 'CoercedArrayRefOfMyModuleObjects',
    coerce => 1,
);

__PACKAGE__->meta->make_immutable();

1;

And this is my MyModule::Object class:

use strict;
package MyModule::Object;
use Mouse;

has x => (
    is => 'rw',
    isa => 'Int',
);

__PACKAGE__->meta->make_immutable();

1;

But whenever I try to create an object and pass it an arrayref of hashes:

my $obj = MyModule->new(objects => [{x => 1}, {x => 2}, {x => 3}]);

I get the following error:

The type constraint 'CoercedArrayRefOfMyModuleObjects' has already been created in Mouse::Util::TypeConstraints and cannot be created again in MyModule::Types ('CoercedArrayRefOfMyModuleObjects' is an implicitly created type constraint) at lib/MyModule/Types.pm line 41.

Does anyone know why this is?

EDIT: I think it has to do with me maybe having use MyModule::Types in multiple places. But I need to use it in multiple locations so that modules can be used on their own. Also, for some reason other types (I have other types defined in my TypeConstraints file) don't seem to be giving me this error. Shouldn't Mouse::Util::TypeConstraints be able to handle being included in to modules that might be used together, so that the modules could be used individually?

srchulo
  • 5,143
  • 4
  • 43
  • 72
  • I think the naming of the type `CoercedArrayRefOfMyModuleObjects` is a bit unlucky. You can pass an actual array ref with `MyModule::Objects` in there and it will work, but it's not coerced. For maintainability, name the types after what they are, not where they come from. The `coerce => 1` is sufficient to tell the next guy you that it might be coerced, and even if the types are _somewhere_, a simple grep will find it. :) – simbabque Jun 09 '15 at 07:15
  • Is there a reason you are using Mouse? If you need something lighter than Moose, consider using [Moo](http://p3rl.org/Moo). There is a nice presentation by SawyerX from NLPW 2014 where he explaines why at https://www.youtube.com/watch?v=r2Fl6Kg1E9I – simbabque Jun 09 '15 at 07:29
  • @simbabque thanks for the suggestions. I'll check out that video! – srchulo Jun 09 '15 at 13:37
  • Please refer to this question [The type constraint 'XYZ' has already been created](http://stackoverflow.com/questions/41550691/the-type-constraint-xyz-has-already-been-created/41551350#41551350) – Tigran Khachikyan Mar 20 '17 at 20:22

0 Answers0