It took me a little while to figure this one out so I thought I post it here, partly to make it easier for myself to find it next time ;-)
I write software for biological applications and I use Moose. My modules often take biological sequence data as input, so I create a subtype for strings that fulfill a regex for valid DNA sequences (in this case I only allow the letters A,G,T, C and N). This is in a package MyApp::MooseX::MyTypes:
Now my modules can define attributes like this:subtype 'DNAString' => as Str => where { $_ && $_=~/^[AGCTN]+$/i} => message {"Not a DNA string: only AGCT or N allowed and cannot be +empty"};
So far so good, but sequences in biological applications in Perl often exist in the form of Bio::Seq objects and I thought it would be nice if my DNAString type could automatically get the sequence string from such objects. However, you can only coerce from Moose built-in types, so I wanted to say: coerce from an incoming object into a sequence string, if that object has a 'seq' method (which returns the sequence as a string in BioPerl).use MyApp::MooseX::MyTypes: has sequence => ( isa => 'DNAString', );
And then you need to tell the constructor that you want to use coercions for this attribute by adding the 'coerce' switch:coerce 'DNAString' => from duck_type( ['seq'] ) => via { $_->seq };
Now all my modules that used to only accept sequence strings, automatically except Bio::Seq objects as well.use MyApp::MooseX::MyTypes: has sequence => ( isa => 'DNAString', coerce => 1, );
|
|---|
| Replies are listed 'Best First'. | |
|---|---|
|
Re: Of moose and ducks (or: how to coerce from non-Moose type objects)
by stvn (Monsignor) on Jan 08, 2011 at 00:59 UTC | |
by tospo (Hermit) on Jan 10, 2011 at 10:51 UTC |