Skip Menu |

This queue is for tickets about the Type-Tiny CPAN distribution.

Report information
The Basics
Id: 105561
Status: resolved
Priority: 0/
Queue: Type-Tiny

People
Owner: Nobody in particular
Requestors: 1nickt [...] gmail.com
Cc:
AdminCc:

Bug Information
Severity: (no value)
Broken in: (no value)
Fixed in: (no value)



Subject: Type::Library messages lost when used with named parameters in Type::Params
Date: Mon, 29 Jun 2015 12:18:33 -0700
To: bug-Type-Tiny [...] rt.cpan.org
From: Nick Tonkin <1nickt [...] gmail.com>
Hi Toby, Thanks for your amazing modules! Ran into a little problem: I've noticed that when I use Types that I make with Type::Library, to validate *named* incoming arguments, with Type::Params, using a slurpy Dict, per the docs, I lose the custom error message set in the library. # in package MyModule::Types declare DBPrefix, as Optional[StrMatch[ qr/ \w+_ /x ]], message { 'The table prefix must end in an underscore. ' }; # in package MyModule use Type::Params qw/ compile /; use My::Types qw/ DBPrefix /; state $validate = compile( DBPrefix ); my ($param) = $validate->( @_ ); # in foo.pl $obj->method( 'bar' ); # output: # The table prefix must end in an underscore. (in $_[0]) at ./foo.pl line 11 # "DBPrefix" is a subtype of "Optional[StrMatch[(?^x: \w+_ )]]" # Value "bar" did not pass type constraint "Optional[StrMatch[(?^x: \w+_ )]]" (in $_[0]+) # $_[0] exists # "Optional[StrMatch[(?^x: \w+_ )]]" constrains $_[0] with "StrMatch[(?^x: \w+_ )]" if +it exists # Value "bar" did not pass type constraint "StrMatch[(?^x: \w+_ )]" (in $_[0]) # "StrMatch[(?^x: \w+_ )]" is defined as: do { !ref($_) and $_ =~ $Types::Standard::_St+rMatch{"(?^x: \\w+_ )"} } [download] <http://www.perlmonks.com/?abspart=1;displaytype=displaycode;node_id=1132514;part=2> That's a little more than I really need, but it gives me my custom message at the beginning. Now, when I want to use named arguments, I follow the manual: state $validate = compile(slurpy Dict[ prefix => DBPrefix ]); #per the docs for named args my ($param) = $validate->( @_ ); # in foo.pl $obj->method( 'bar' ); # output : # Reference {"prefix" => "bar"} did not pass type constraint "Dict[prefix=>DBPrefix]" (in +$SLURPY) at ./foo.pl line 11 [download] <http://www.perlmonks.com/?abspart=1;displaytype=displaycode;node_id=1132514;part=3> I need to use named args because some of them are completely optional. But I want to be able to return an error that tells the user how to fix the error! Is there a way around this? Thanks, Nick
I've just been bitten by this same problem, and I've dug a bit. When Type::Params compiles the parameter checker, it goes through each constraint, and generates a snipped of code for each of them. To throw exceptions, it calls Type::Tiny::_failed_check with the "uniq" value of the constraint (so that it does not have to try to serialise the constraint definition, or otherwise stringify a reference). *But*, there is nothing that keeps a reference to the constraint after the end of "compile", so the constraint will be DESTROYed, and removed from the %ALL_TYPES map. Which means that _failed_check will not have a constraint object to call ->get_message on, and will fall back on the simpler message. Suggestion: capture the constraints in %env inside "compile" (but I'm not confident enough to write a patch, sorry)
Have you looked at the betas for the next version of Type::Params? It introduces a slightly better way of handling functions with named parameters: https://metacpan.org/pod/release/TOBYINK/Type-Tiny-1.001_002/lib/Type/Params.pm#Named-Parameters I *think* the error messages generated should be better.
Just gonna close this and say "use Type::Params 'compile_named'"