Type::Tiny Tricks #1: Quick Intersections

This is a very old article. It has been imported from older blogging software, and the formatting, images, etc may have been lost. Some links may be broken. Some of the information may no longer be correct. Opinions expressed in this article may no longer be held.

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.