1nickt has asked for the wisdom of the Perl Monks concerning the following question:

Hello monks,

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 "StrMatc +h[(?^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::_StrMatch{"(?^x: \\w+_ )"} }

That's a little more than I really need, but it gives me my custom message at the beginning.

Now, when I want to go to 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[pre +fix=>DBPrefix]" (in $SLURPY) at ./foo.pl line 11

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!

Has anyone figured a way around this? Thanks ...

Replies are listed 'Best First'.
Re: Type::Library messages lost when used with named parameters in Type::Params
by stevieb (Canon) on Jun 29, 2015 at 22:39 UTC

    A workaround for the actual issue, but can you wrap the call in an eval() block, check the error eval catches (if it does catch anything), and print your custom message?

    #!/usr/bin/perl use warnings; use strict; sub divide { return 1 / 0; } my $x; eval { $x = divide(); }; if ($@ =~ /Illegal division/){ print "Don't divide by zero, dummy!\n"; # die with called function's error if required die $@; } print "$x\n";

    -stevieb

      Hi Stevie, thanks, yeah, that would work. But I assume that the Type::* modules do that under the hood ... If I had to eval a test to print a message, there wouldn't be much point in using the whole Type::* infrastructure....

      As the docs say, the default message is a "vaguely sensible default." So if I can't get my messages to print, it won't be the end of the world. But it's frustrating that it only stops working in a certain case.

      I'm going to see if I can figure out how to fix it in Type::Tiny before I give up :)