Beefy Boxes and Bandwidth Generously Provided by pair Networks
Problems? Is your data what you think it is?
 
PerlMonks  

Some Moose questions

by tj_thompson (Monk)
on Nov 19, 2010 at 22:10 UTC ( #872597=perlquestion: print w/ replies, xml ) Need Help??
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:

subtype 'NewType', as 'Str', where {$_ =~ /^new_/}; coerce 'NewType', from 'Str', via { 'new_'.$_ };
With this new code, I get:
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 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
However, if I add this to the main package:

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 19
So 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:

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);
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_'.$_ };
So the big question. Should you try to quote your type names? Is the original concern valid? If it is, why do so few module authors do so? Granted I could see the problem coming up only rarely, but I could also see the issue being a real pain to debug. And if you should quote the type names, how do you get the above code to work properly?

Comment on Some Moose questions
Select or Download Code
Re: Some Moose questions
by stvn (Monsignor) on Nov 19, 2010 at 22:26 UTC

    You are confusing core Moose types with MooseX::Types.

    Core Moose types (those created with Moose::Util::TypeConstratints are not the same as MooseX::Types created types. If you are not using MooseX::Types, then you will always want to quote your type names because of exactly the documented issue you quoted. However with MooseX::Types, a subroutine is created for you which you can then use as a bareword so quoting is not needed (however you do need to watch out for automagic stringification using the fat comma).

    -stvn
      Excellent, that makes me feel better about not using quotes then. I had planned to use MooseX::Types. There's just so much Moose documentation that I was getting confused while I waded through it all. I appreciate you taking the time out to help!
      Oooh so let's make certain I understand this then. That means the MooseX::Types::Moose is giving you the core Moose types as MooseX::Types types which then means you don't have to worry about quoting those either, right?

        Yes, exactly.

        -stvn

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://872597]
Approved by Corion
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others chanting in the Monastery: (11)
As of 2014-10-24 18:18 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    For retirement, I am banking on:










    Results (134 votes), past polls