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]; const char* p; (void)Gconvert(nv, NV_DIG, 0, buf); p = &buf[0]; 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