NAME

Data::Filter::Abstract - generate Perl filter subs from data structures

SYNOPSIS

use Data::Filter::Abstract;

my $filter = Data::Filter::Abstract->new({
    foo => [ 1, "bar", qr/\d+/ ],
    baz => { '>' => 2, '<' => 5 },
});

# Use as a CODE reference
my $match = $filter->({ foo => 1, baz => 3 }); # true

# Get the generated Perl expression as text
print "$filter\n"; 

DESCRIPTION

Data::Filter::Abstract wraps the expression-generation DSL provided by Data::Filter::Abstract::Util and produces executable Perl predicates.

It compiles a hash- or array-based filter description into:

  • A string expression suitable for embedding in a sub { ... } block

  • A compiled coderef that can be called directly with a hash reference

Objects overload stringification to return the expression and the code dereference operator to return the coderef.

CONSTRUCTION

new

my $filter = Data::Filter::Abstract->new($dsl);

$dsl is any input accepted by simple_sub in Data::Filter::Abstract::Util (hash, array, operator hash, scalar, etc.).

The constructor converts the input data structure into a Perl expression string and compiles the expression into a coderef, or dies if the generated coderef cannot be compiled.

USAGE

As a CODE reference

The object can be used directly as a predicate:

my $match = $filter->($row);

Accessing the coderef

my $coderef = $filter->to_subref;
$coderef->($row);

Accessing the expression string

my $expr = $filter->to_source;
print "$expr\n";

OVERLOADING

  • Stringification

    Returns the generated expression.

  • Code dereference

    Returns the compiled coderef.

CAVEAT

This module uses eval to compile Perl code. Embedded code references are executed verbatim.

DATA STRUCTURE CONVERSION

GENERAL SEMANTICS

The data-structure-to-filter-sub attempts to mimic SQL::Abstract as closely as possible.

  • All generated expressions assume $_ is a hash reference.

  • Field access is performed as $_-{field}>.

  • Hashes represent logical AND.

  • Arrays represent logical OR, unless explicitly overridden by logical operators.

  • Generated expressions are syntactically valid Perl code suitable for eval.

BASIC FILTER FORMS

Scalar equality

simple_sub(foo => "bar")

Generates a string equality comparison:

($_->{foo} eq "bar")

If the value looks like a number, numeric comparison is used:

simple_sub(foo => 1)
# ($_->{foo} == 1)

Regular expressions

simple_sub(foo => qr/12/)
simple_sub(foo => qr/[a-z]/i)

Generates regex match expressions:

($_->{foo} =~ qr/12/)
($_->{foo} =~ qr/[a-z]/i)

Hash form (implicit AND)

simple_sub({ bar => 1, baz => "wq", boo => qr/12/ })

Equivalent to:

($_->{bar} == 1)
&& ($_->{baz} eq "wq")
&& ($_->{boo} =~ qr/12/)

simple_hash behaves identically.

ARRAY FORMS

Simple OR array

simple_sub(foo => [ 1, "wq", qr/12/ ])

Generates a logical OR over the values:

($_->{foo} == 1)
|| ($_->{foo} eq "wq")
|| ($_->{foo} =~ qr/12/)

Arrays of operator expressions

simple_array(foo => [ { '==', 2 }, { '>', 5 } ])

Generates:

($_->{foo} == 2) || ($_->{foo} > 5)

LOGICAL ARRAYS

Arrays may begin with a logical operator to control how elements are combined.

AND logic

simple_sub(foo => [ -and => { '==', 2 }, { '>=', 5 } ])

Generates:

($_->{foo} == 2) && ($_->{foo} >= 5)

OR logic

simple_sub(foo => [ -or => { '==', 2 }, { '>=', 5 } ])

Generates:

($_->{foo} == 2) || ($_->{foo} >= 5)

OPERATOR HASHES (FUNCTION HASHES)

A field value may be a hash mapping operators to values.

simple_sub(foo => { '>' => 12, '<' => 23 })

Generates:

($_->{foo} < 23) && ($_->{foo} > 12)

The order of operators is not significant.

Supported operators (as tested)

  • String operators

    eq ne lt le gt ge
  • Numeric operators

    == != < <= > >=
  • Regex operators

    =~ !~

OPERATORS WITH ARRAY VALUES

Equality with array

simple_sub(status => { eq => [ 'assigned', 'in-progress', 'pending' ] })

Generates an OR expression:

($_->{status} eq "assigned")
|| ($_->{status} eq "in-progress")
|| ($_->{status} eq "pending")

Equivalent logic may also be expressed via a logical array:

simple_sub(status => [
    -or =>
    { eq => 'assigned' },
    { eq => 'in-progress' },
    { eq => 'pending' },
])

Regex operators with arrays

simple_sub(foo => { '=~' => [ qr/12/, qr/23/i ] })

Generates:

($_->{foo} =~ qr/12/)
|| ($_->{foo} =~ qr/23/i)

Non-regex values are coerced to regexes:

simple_sub(foo => { '=~' => [ "12", qr/23/i ] })

UNDEF HANDLING

simple_sub(user => undef)

Generates:

(! defined $_->{user})

Operator hashes may also compare against undef, though some combinations are known to be problematic (see tests marked as failing).

FIELD-TO-FIELD COMPARISON (SCALAR REF)

If the value is a scalar reference, it is interpreted as another field name.

simple_sub(foo => \"bar")

Generates a dynamic comparison:

( (looks_like_number($_->{foo}))
    ? ($_->{foo} == $_->{bar})
    : ($_->{foo} eq $_->{bar})
)

This form may also appear inside logical arrays.

CODE REFERENCES

A code reference may be supplied as a filter.

simple_sub(sub { $_->{foo}->{bar} > 5 })

or

simple_sub(foo => sub { $_->{foo}->{bar} > 5 })

The code reference is deparsed and embedded verbatim:

(sub { use strict; $_->{'foo'}{'bar'} > 5; })

The field name is ignored when a code reference is supplied.

MIXED COMPLEX EXPRESSIONS

Arrays may contain mixed value types:

simple_sub(foo => [
    1,
    "wq",
    qr/12/,
    sub { shift()->{foo}->{bar} > 5 }
])

Generates a logical OR over all components.

SEE ALSO

Data::Filter::Abstract, SQL::Abstract

AUTHOR

Simone Cesano <scesano@cpan.org>

LICENSE

This software is copyright (c) 2025 by Simone Cesano.

This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself.