Perl 6 lets you constrain variable values with types, but you don’t have to limit yourself to the built-in types. Once defined, these act like the built-in types. Here are some subsets I’ve stolen from Brad Clawsie’s Subsets::Common module:
my package EXPORT::DEFAULT { ... subset Pos of Numeric where * > 0; subset Neg of Numeric where * < 0; subset Zero of Numeric where * == 0; subset UNumeric of Numeric where * >= 0; subset Even of Int where * % 2 == 0; subset Odd of Int where * % 2; subset Time::Hour12 of PosInt where * ~~ 1 .. 12; subset Time::Hour24 of Int where * ~~ 0 .. 23; subset Time::Minute of Int where * ~~ 0 .. 59; subset Time::Second of Int where * ~~ 0 .. 59; ... }
The subset
started the declaration and is followed by the name you want for the new type. This is a subset because you base it on an existing type that you declare with of
. After that, you can use a where
clause to refine your new type.
And, Brad put these in a package where he declared that everything is exported.
Here’s one that I created for my Perl 6 version of Chemistry::Elements. Don’t worry so much about what’s in the code; think more about the ability to have any code you need to decide if the value fits the constraint that you like. Here’s the type I defined to constrain an integer to a known atomic number (typically called Z from the German word Zahl, as in Atomzahl):
subset ZInt of Cool is export where { state ( $min, $max ) = %names.keys.sort( { $^a <=> $^b } ).[0,*-1]; ( $_.truncate == $_ and $min <= $_ <= $max ) or note "Expected a known atomic number between $min and $max, but got $_" and False; };
For my subset, I exported it by declaring it is export
so other people using the module could use the type outside of my module. Most notably (heh), I can give a specific error message when the value doesn't match.
Since you can’t compare Complex numbers with = and the likes, I’d recommend to use Real instead of Numeric as the nominal type for Pos, Neg and so on.
Pull request sent!
“where * ~~ 0..59” is redundant; since it’s already being smart-matched, this can just be “where 0..59”.