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; };