Type::Tiny Tricks #1: Quick Intersections
Type::Tiny objects overload the &
(bitwise and) operator to build a type constraint intersection. For example:
package Local::Eg1; use Moose; use Types::Standard -types; has foo => ( is => "ro", isa => ArrayRef[Int] & HashRef[Int], ); __PACKAGE__->meta->make_immutable;
Though that example isn't especially useful. Do you remember Venn diagrammes? Intersections are that small overlapping section in the middle. So the value for foo
needs to be something that is simultaneously an arrayref and a hashref. (Which no value could satisfy.)
But there are ways intersections can be used more usefully.
Perhaps you want a class name that matches a certain regexp:
has formatter => ( is => "ro", isa => ClassName & StrMatch[ qr/^DateTime::Format::/ ], );
Type::Tiny is able to coerce certain things such as coderefs into Type::Tiny objects. Combining that ability with intersections allows for a very lightweight method of creating subtypes:
has even_number => ( is => "ro", isa => Int & sub { $_ % 2 == 0 }, );
Caveats
The &
character in Perl is not just the bitwise and operator, but is also used in Perl-4-style subroutine calls:
$sum = &add_nums(1, 2, 3);
Because of this, the Perl parser uses some heuristics to figure out what you meant by &
. Sometimes it gets things wrong. One example I've found is: ArrayRef & HashRef
which Perl interprets as meaning ArrayRef( &HashRef )
. This can usually be solved by adding extra parentheses: ArrayRef() & HashRef
.
Leave a comment