|Come for the quick hacks, stay for the epiphanies.|
Exploring Type::Tiny Part 5: match_on_typeby tobyink (Canon)
|on Aug 19, 2018 at 18:41 UTC||Need Help??|
Type::Tiny is probably best known as a way of having Moose-like type constraints in Moo, but it can be used for so much more. This is the fifth in a series of posts showing other things you can use Type::Tiny for. This article along with the earlier ones in the series can be found on my blog and in the Cool Uses for Perl section of PerlMonks.
It's pretty common to do things like this:
Type::Utils provides a perhaps slightly neater way to do this:
The match_on_type function takes a value and a set of type–coderef pairs, dispatching to the first coderef where the value matches the type constraint. This function is stolen from Moose::Util::TypeConstraints.
You can get an order of magnitude faster though by doing something similar to what Type::Params does — compiling the match once, then calling it as needed.
Let's look at a naïve (and wrong) way to do this first and examine the problems:
The big problem here is that the first time process_data is called, the matcher will close over $self and $data. Subsequent calls to $matcher will reuse the same closed over variables. Oops.
The simplest way of solving this is to take advantage of the fact that a compiled matcher (unlike match_on_type) can take a list of arguments, not just one. Only the first argument is used for the type matching, but all arguments are passed to the coderefs on dispatch.
Like many Type::Tiny interfaces that expect coderefs, compile_match_on_type also accepts strings of Perl code as an alternative, and is able to optimize things better if those are supplied:
The coderefs compiled by compile_match_on_type should be very efficient. The technique is very similar to how Type::Coercion compiles coercions.