Perl structure for checking data types

So, I would like to bring a little bit of mouse speed to my other routines and check a little à la type

sub mysub { my ($self, $int) = @_; assert_int($int, 'int[1]'); } 

Subroutine arguments are the data for approval and an optional name for this data. This means that we get a more useful error message, for example.

 Assertion error! 'int[1]' is not an integer; got 'HASH(0xXXXXXXXXX)' 

Writing it in pure Perl was not difficult. When you compare it to the speed in Mouse and gfx of another Data :: Util module, ~ 4 times faster than pure Perl, it is obvious that pure XS solutions have the upper part, but they miss this optional parameter name. Writing a small wrapper around the Data :: Util check functions is still slower than using XS directly.

Does anyone know of a set of fast utilities for asserting data types that let you pass this field name to an assertion?

EDIT after @ikegami answers how to use a system such as Mouse, it seems that performance is still lacking compared to using only XS libraries. Thus, the question is transformed more. Is there an XS-based framework that can provide custom error messages, or at least lets you say what is called an attribute.

EDIT , this is the code I'm comparing to performance right now. This was based on gfx work in Data::Util and Mouse XS mode. This gives us 5x speed on a pure Perl solution. Comparing C with Perl is somewhat unfair, so I was wondering if there was already an existing environment that could give this performance, but with the right kind of error message. I do not want to write this material if someone else did this :)

 use Inline C => <<'END_C'; static int S_nv_is_integer(pTHX_ NV const nv) { if(nv == (NV)(IV)nv){ return TRUE; } else { char buf[64]; /* Must fit sprintf/Gconvert of longest NV */ const char* p; (void)Gconvert(nv, NV_DIG, 0, buf); p = &buf[0]; /* -?[0-9]+ */ if(*p == '-') p++; while(*p){ if(!isDIGIT(*p)){ return FALSE; } p++; } return TRUE; } } int assert_int(SV* sv, char* attributeName) { assert(sv); int result; if(SvPOKp(sv)){ int const num_type = grok_number(SvPVX(sv), SvCUR(sv), NULL); result = num_type && !(num_type & IS_NUMBER_NOT_INT); } else if(SvIOKp(sv)){ result = TRUE; } else if(SvNOKp(sv)) { result = S_nv_is_integer(aTHX_ SvNVX(sv)); } else { result = FALSE; } if(! result) { croak("'%s' was not an integer; got '%s'", attributeName, SvPV(sv, PL_na)); } return result; } END_C 
+4
source share
1 answer

If you want to use the mouse without stopping anything.

 my $int_constraint = Mouse::Util::TypeConstraints::find_type_constraint('Int'); sub mysub { my ($self, $int) = @_; $int_constraint->assert_valid($int); ... } 

If you use check or die instead of assert_valid , if you want to provide your own message.

I used this with Moose, but it looks like it should work with Mouse too.

+3
source

All Articles