Data::Checks(3pm)

πŸ“¦
version 0.11 Β· 5 versions
, in ubuntu stonking

πŸ’– Data::Checks β€” value constraint checking, bestie edition πŸ’–

okay so like. Data::Checks. It's a Perl module (manual page Data::Checks(3pm), in case you were wondering who she is) and she is literally the moment for constraint checking. Value constraint checking, specifically. Let's get into it ✨


🌸 SYNOPSIS 🌸

not one, not two, but THREE whole ways to use this, bestie. she's versatile, she contains multitudes πŸ’…

With Signature::Attribute::Checked:

use v5.26;
use Sublike::Extended 0.29 'sub';
use Signature::Attribute::Checked;

use Data::Checks qw( Str );

sub greet ( $message :Checked(Str) ) {
   say "Hello, $message";
}

greet( "world" );  # is fine
greet( undef );    # throws an exception

With Object::Pad::FieldAttr::Checked:

use v5.22;
use Object::Pad;
use Object::Pad::FieldAttr::Checked;

use Data::Checks qw( Str );

class Datum {
   field $name :param :reader :Checked(Str);
}

my $x = Datum->new( name => "something" );  # is fine
my $y = Datum->new( name => undef );        # throws an exception

With Syntax::Operator::Is on Perl v5.38 or later:

use v5.38;
use Syntax::Operator::Is;

use Data::Checks qw( Num Object );

my $x = ...;

if($x is Num) {
   say "x can be used as a number";
}
elsif($x is Object) {
   say "x can be used as an object";
}

see? three vibes, zero problems. moving on πŸ¦‹


🌈 DESCRIPTION 🌈

So this module hands you a whole lil collection of functions that implement various value constraint checking behaviours. These are the parts you actually get to see in Perl code β€” the stuff that shows up the second you type use Data::Checks ... and import something. cute, right?

It ALSO ships the underlying common framework XS functions, which are there to help you write modules that actually implement this kind of constraint checking yourself. Those bits are NOT visible in Perl code β€” nope β€” instead they're made visible at the XS level by the #include "DataChecks.h" directive. iykyk 🧚

And if you want to see other CPAN modules that make direct use of these constraint checks, scroll up, the SYNOPSIS section has several examples. go look, they're right there.


πŸ‘‘ CONSTRAINTS πŸ‘‘

The following constraint checks are inspired by the same-named ones over in Types::Standard. You can call them fully-qualified, or import them lexically into whatever scope you're in. your call, both slay πŸ’–

πŸ“’ note to the Types::Standard girlies: some of these functions behave slightly differently. specifically, these constraints are generally happy to accept an object reference to a class that provides a conversion overload β€” whereas the Types::Standard ones often are not. also, functions that are parametric take their parameters in normal Perl function argument lists, not wrapped in additional array references. important!!! don't skip this part 😭

Defined

Defined()

Accepts any defined value. Rejects only undef. that's the whole job, and she does it flawlessly ✨

Object

Object()

Accepts any blessed object reference. Rejects non-references, and rejects references to unblessed data. if you were hoping to sneak an unblessed thing past her, no πŸ’€

Str

Str()

Accepts any defined non-reference value, OR a reference to an object in a class that overloads stringification. Rejects undefined stuff, unblessed references, and references to objects in classes that do NOT overload stringification. stringification girlies only πŸŽ€

StrEq

StrEq($s)
StrEq($s1, $s2, ...)

Since version 0.05.

Accepts any value that passes the Str check, AND additionally is exactly equal to any of the given strings. exact match, no approximations, periodt πŸ’…

StrMatch

StrMatch(qr/pattern/)

Since version 0.08.

Accepts any value that passes the Str check, AND additionally matches the given regexp pattern.

⚠️ Remember that the pattern must be supplied as a qr/.../ expression β€” not simply m/.../ or /.../. the regex must be a qr one, bestie. do not fight this.

Num

Num()

Accepts any defined non-reference value that is either a plain number, or a string that could be used as one without warning, or a reference to an object in a class that overloads numification.

Rejects undefined, not-a-number, strings that would raise a warning if converted to a number, unblessed references, and references to objects in classes that do not overload numification.

she's strict about numbers, and honestly? she should be πŸ”₯

NumGT

NumGE

NumLE

NumLT

NumGT($bound)
NumGE($bound)
NumLE($bound)
NumLT($bound)

Since version 0.05.

Accepts any value that passes the Num check, and additionally is within the bound given. NumGT and NumLT exclude the bound value itself, while NumGE and NumLE include it. get it? GT/LT = exclusive besties, GE/LE = inclusive besties 🌸

NumRange

NumRange($boundge, $boundlt)

Since version 0.05.

Accepts any value that passes the Num check, and additionally is between the two bounds given. The lower bound is inclusive, and the upper bound is exclusive.

This choice is made so that a set of NumRange constraints can easily be created that cover distinct sets of numbers:

NumRange(0, 10), NumRange(10, 20), NumRange(20, 30), ...

To implement checks with both lower and upper bounds but other kinds of inclusivity, use two Num... checks combined with an All(). For example, to test between 0 and 100 inclusive at both ends:

All(NumGE(0), NumLE(100))

Combinations like this are internally implemented as efficiently as a single NumRange() constraint. no cap, that's a real optimisation and she ate πŸ‘‘

NumEq

NumEq($n)
NumEq($n1, $n2, ...)

Since version 0.05.

Accepts any value that passes the Num check, and additionally is exactly equal to any of the given numbers. exact, like I said.

Isa

Isa($classname)

Since version 0.04.

Accepts any blessed object reference to an instance of the given class name, or a subclass derived from it β€” i.e. anything accepted by the isa operator. inheritance girlies, you're covered 🫢

Can

Can($methodname)
Can($methodname1, $methodname2, ...)

Since version 0.11.

Accepts any blessed object reference to an instance in a class, or a class name directly, that has ALL of the given method names β€” i.e. anything that passes a ->can test on every name. every single one. all of them. not just one.

To accept only object references and not package names, combine this check with Object by using the All combination:

All(Object, Can($methodname, ...))

ArrayRef

ArrayRef()

Since version 0.07.

Accepts any plain reference to an array, or any object reference to an instance of a class that provides an array dereference overload. πŸ“

HashRef

HashRef()

Since version 0.07.

Accepts any plain reference to a hash, or any object reference to an instance of a class that provides a hash dereference overload. πŸ“

Callable

Callable()

Since version 0.06.

Accepts any plain reference to a subroutine, or any object reference to an instance of a class that provides a subroutine dereference overload. call me maybe? no wait, that's the next one 😭

Maybe

Maybe($C)

Since version 0.04.

Accepts undef in addition to anything else accepted by the given constraint. she's flexible like that πŸ’œ

Any

Any($C1, $C2, ...)

Since version 0.07.

Accepts a value that is accepted by at least one of the given constraints. Rejects if none of them accept it.

At least one constraint is required β€” it is an error to try to call Any() with no arguments. If you need a constraint that accepts any value at all, see All. don't do it. she will yell at you. kindly. but still.

$C1 | $C2 | ...

Since version 0.08.

This function is used to implement | operator overloading, so constraint checks can be written using this more convenient syntax. cute AND functional, the dream 🌈

All

All($C1, $C2, ...)
All()

Since version 0.07.

Accepts a value that is accepted by every one of the given constraints. Rejects if at least one of them rejects it. one hater and it's over πŸ’€

Note that if no constraints are given, this accepts all possible values. This may be useful as an accept-all fallback case for generated code, or other situations where it is required to provide a constraint check but you do not wish to constrain allowed values. she's giving generous, and I respect it πŸ™ˆ


✨ CONSTRAINT METHODS ✨

While not intended to be called from regular Perl code, these constraints still act like objects with the following methods. look at them, being all object-y ✨

check

$ok = $constraint->check( $value );

Since version 0.09.

Returns a boolean value indicating whether the constraint accepts the given value. that's it. that's the method. simple, effective, iconic πŸ‘‘

πŸ”₯ XS FUNCTIONS πŸ”₯

okay bestie, this next bit is for the XS girlies πŸ’… β€” these are the functions that the DataChecks.h header file hands you so you can do value constraint checking from inside XS modules. yes you, writing C, I see you, you're doing amazing.


✨ boot_data_checks ✨

void boot_data_checks(double ver);

call this one from your BOOT section, bestie β€” it's literally what initialises the module and loads up all the rest of the support functions. no boot, no functions, periodt.

ver should be either 0 or a decimal number for the module version requirement. like, for example:

boot_data_checks(0.01);

slay. moving on 🌸


✨ make_checkdata ✨

struct DataChecks_Checker *make_checkdata(SV *checkspec);

this one creates a struct DataChecks_Checker structure, which wraps up the whole intent of the value constraint check 🫢. that returned value is what you pass as the checker argument to all the other functions down below. keeping the gang together, as one does.

the actual constraint check itself is specified by the SV you hand in as checkspec, and that should come directly from the user code β€” straight from the source, no middleman. and here's the thing: the constraint check can be specified in any of three ways:

  • an object reference in a class which has a check method. value checks get invoked like
$ok = $checkerobj->check( $value );
  • a package name as a plain string of a package which has a check method. value checks get invoked like
$ok = $checkerpkg->check( $value );
  • a code reference πŸ‘€. value checks get invoked with a single argument, like
$ok = $checkersub->( $value );
⚠️ okay so since version 0.09 this form is deprecated β€” because it doesn't easily support a way to query the constraint for its name or its stringified form, which is genuinely useful when you're generating error messages. rip. it had a good run 😭
  • and additionally, the constraint check functions provided by this module may be implemented using any of the above mechanisms, or may use an unspecified fourth different mechanism entirely. outside code should not rely on what that mechanism may be. mind your business, respectfully πŸŽ€

once it's constructed into a checker structure, the choice of which implementation is used is fixed β€” locked in, no take-backs, main character energy. and if a method lookup is involved, its result is stored directly as a CV pointer so later invocations are speedy ⚑. in either of the first two cases, the reference count on the checkspec SV gets increased to account for the argument value used on each invocation. in the third case, the reference SV is not retained, but the underlying CV it refers to has its reference count increased instead. balanced, as all things should be πŸ’œ


✨ free_checkdata ✨

void free_checkdata(struct DataChecks_Checker *checker);

releases any stored SVs in the checker structure, and then releases the structure itself. it's giving cleanup era ✨ never skip the free bestie.


✨ gen_assertmess ✨

void gen_assertmess(struct DataChecks_Checker *checker, SV *name, SV *constraint);

generates and stores a message string for the assert message that make_assertop and assert_value will use. the message comes out looking like

NAME requires a value satisfying CONSTRAINT

both the name and constraint SVs are used as temporary strings to generate that stored message string β€” and that's all they're used for. neither SV is retained by the checker directly. ships them off to string town and that's it πŸ¦‹


✨ make_assertop ✨

OP *make_assertop(struct DataChecks_Checker *checker, OP *argop);

this is just a shortcut for calling make_assertop_flags with flags set to zero. convenience queen πŸ‘‘


✨ make_assertop_flags ✨

OP *make_assertop_flags(struct DataChecks_Checker *checker, U32 flags, OP *argop);

creates an optree fragment for a value check assertion operation πŸ”₯

so here's the deal: you give it an optree fragment in scalar context that generates an argument value (argop), and it constructs a larger optree fragment that consumes that value and checks that it's accepted by the constraint check given by checker. the behaviours of the returned optree fragment depend on the flags:

  • if flags is OPf_WANT_VOID, the returned optree will yield nothing. nothing at all. void vibes πŸ’€
  • if flags is zero, the return behaviour is not otherwise specified. no promises, no cap.

✨ check_value ✨

bool check_value(struct DataChecks_Checker *checker, SV *value);

checks whether a given SV is accepted by the given constraint check, and returns true if it is, or false if it's not. simple. honest. iconic 🫢


✨ assert_value ✨

void assert_value(struct DataChecks_Checker *checker, SV *value);

checks whether a given SV is accepted by the given constraint check, and if it's not, it throws its assertion message at you. dramatic? yes. effective? also yes 😀


πŸ“ TODO πŸ“

the wishlist, bestie. manifesting ✨

  • unit constraints β€” maybe Int, some plain-only variants of Str and Num, some reference types, etc...
  • structural constraints β€” HashOf, ArrayOf, etc...
  • think about a convenient name for inclusive-bounded numerical constraints 🧚
  • look into making const-folding work with the MIN .. MAX flip-flop operator
  • performance enhancements for lists of many values in StrEq, NumEq, etc
  • performance enhancement of Can by caching per package name

πŸ‘‘ AUTHOR πŸ‘‘

Paul Evans <leonerd@leonerd.org.uk>


and that's the whole page, bestie πŸ’– this was Data::Checks, part of perl v5.42.3, dated 2026-08-20. go forth and validate your values, no cap πŸŒˆπŸ’…βœ¨

πŸ“¦ where this page comes from