tj_thompson has asked for the wisdom of the Perl Monks concerning the following question:
I've just been picking up and messing with Moose and I've been left with a few questions about it.
First off, in the Moose::Util::TypeConstraints documentation on cpan, the author mentions this:
It is always a good idea to quote your type names.
This prevents Perl from trying to execute the call as an indirect object call. This can be an issue when you have a subtype with the same name as a valid class.
For instance:
subtype DateTime => as Object => where { $_->isa('DateTime') };
will just work, while this:
use DateTime; subtype DateTime => as Object => where { $_->isa('DateTime') };will fail silently and cause many headaches. The simple way to solve this, as well as future proof your subtypes from classes which have yet to have been created, is to quote the type name:
use DateTime; subtype 'DateTime' => as 'Object' => where { $_->isa('DateTime') };
However, he seems to be just about the only one that does quote his type names. His reasoning seems sound though, so I figured I'd stick with it.
Unfortunately, it seems to be hit and miss. I have the following code:
use strict; use warnings; package Foo; use Moose; use TmpTypes qw(NewType); has 'item' => (isa => NewType, is => 'rw', required => 1, coerce => 1); sub is_new { my ($self, $item) = @_; return "Yup, ($item) is new!\n" if (is_NewType($item)); return "Nope, ($item) is old.\n"; } package main; use TmpTypes qw(NewType); my $obj = Foo->new(item => 'car'); my $thing = $obj->item; print "Is $thing new? ".$obj->is_new($thing); $thing = 'house'; print "Is $thing new? ".$obj->is_new($thing); $thing = to_NewType('House'); print "Is $thing new? ".$obj->is_new($thing);
And:
package TmpTypes; use strict; use warnings; use MooseX::Types -declare => [qw(NewType)]; use MooseX::Types::Moose qw(Str); subtype NewType, as Str, where {$_ =~ /^new_/}; coerce NewType, from Str, via { 'new_'.$_ };
This works as expected. Now I add quotes to all my type names. Here in the main file:
has 'item' => (isa => 'NewType',
And here in the TmpTypes package:
With this new code, I get:subtype 'NewType', as 'Str', where {$_ =~ /^new_/}; coerce 'NewType', from 'Str', via { 'new_'.$_ };
WARNING: String found where Type expected (did you use a => instead of a , ?) at TmpTypes.pm line 12However, if I add this to the main package:
WARNING: String found where Type expected (did you use a => instead of a , ?) at TmpTypes.pm line 12
WARNING: String found where Type expected (did you use a => instead of a , ?) at TmpTypes.pm line 16
WARNING: String found where Type expected (did you use a => instead of a , ?) at TmpTypes.pm line 16
You cannot coerce an attribute (item) unless its type (TmpTypes::NewType) has a coercion at tmp8.pl line 10
Attribute (item) does not pass the type constraint because: Validation failed for 'TmpTypes::NewType' with value car (not isa TmpTypes::NewType) at /nfs/pdx/disks/nehalem.pde.077/perl/lib64/site_perl/x86_64-linux/Moose/Meta/Attribute.pm line 883
use Moose::Util::TypeConstraints; These warnings and errors go away and I'm left with:
MooseX::Types::__ANON__(): Unable to find type 'NewType' in library 'TmpTypes' at tmp8.pl line 19So first question, Why is this module necessary to quote your type names?
I traced the new error message, and find out that it stems from this line in the Foo class and is due to the is_NewType function: return "Yup, ($item) is new!\n" if (is_NewType($item)); Once I remove that line, the code again works until encountering the to_NewType function in the main package (which it says is an undefined subroutine &main::to_NewType). It looks like while everything else works with the quoted type name, the to_$type and is_$type functions aren't properly exported? So onto my last questions:
Is the problem just an error in the code that is causing this failure (this stuff's pretty new to me)? For completeness, here's the final code:
And:use strict; use warnings; use Moose::Util::TypeConstraints; package Foo; use Moose; use TmpTypes qw(NewType); has 'item' => (isa => 'NewType', is => 'rw', required => 1, coerce => 1); sub is_new { my ($self, $item) = @_; return "Yup, ($item) is new!\n" if (is_NewType($item)); return "Nope, ($item) is old.\n"; } package main; use TmpTypes qw(NewType); my $obj = Foo->new(item => 'car'); my $thing = $obj->item; print "Is $thing new? ".$obj->is_new($thing); $thing = 'house'; print "Is $thing new? ".$obj->is_new($thing); $thing = to_NewType('House'); print "Is $thing new? ".$obj->is_new($thing);
package TmpTypes; use strict; use warnings; use MooseX::Types -declare => [qw(NewType)]; use MooseX::Types::Moose qw(Str); subtype 'NewType', as 'Str', where {$_ =~ /^new_/}; coerce 'NewType', from 'Str', via { 'new_'.$_ };
|
---|
Replies are listed 'Best First'. | |
---|---|
Re: Some Moose questions
by stvn (Monsignor) on Nov 19, 2010 at 22:26 UTC | |
by tj_thompson (Monk) on Nov 19, 2010 at 22:46 UTC | |
by stvn (Monsignor) on Nov 20, 2010 at 01:48 UTC | |
by tj_thompson (Monk) on Nov 19, 2010 at 22:38 UTC |