The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.

NAME

Brick::Selectors - Connect the input data to the closures in the pool

SYNOPSIS

        use Brick::Selectors;

DESCRIPTION

Selectors test a condition, but they don't fail if the test doesn't work. Instead of die-ing, they return 0. Composers can use selectors to decide if they want to continue with the rest of the composition or simply skip it and try something else. This requires something like Brick::Composers::__compose_pass_or_skip or Brick::Composers::__compose_pass_or_stop that are designed to handle selectors.

The basic use goes like this. I'll make up the completely fake situation where I have to validate a number from user input. If it's odd, It has to be greater than 11 and prime. If it's even, it has to be less than 20 and it has to be a tuesday. Here's the tree of decisions:

                                                        some value
                              /    \
                             /      \
                           odd       even
                          /  |       |  \
       _is_prime  -------+   |       |   +----- _is_tueday
                             |       |
                            /         \
                           /           \
                        > 11          < 20

Now, I have to compose subroutines that will do the right thing. The first step is to decide which side of the tree to process. I'll make some selectors. These won't die if they don't pass:

        my $even_selector = $bucket->_is_even_number;
        my $odd_selector  = $bucket->_is_even_number;

I put the selectors together with the subroutines that should run if that selector is true. The selector tells __compose_pass_or_stop to skip the rest of the subroutines without die-ing. The branch effectively turns into a null operation.

        my $even_branch = $brick->__compose_pass_or_stop(
                $even_selector,
                $brick->_is_tuesday,
                );

        my $odd_branch  = $brick->__compose_pass_or_stop(
                $odd_selector,
                $brick->_is_prime( { field => 'number_field_name' } ),
                );

I put the branches together, perhaps with __compose_pass_or_skip. When the first branch runs, if the value isn't even then the selector stops the subroutine in $even_branch and control skips to $odd_branch.

        my $tester      = $brick->__compose_pass_or_skip(
                $even_branch,
                $odd_branch,
                );

Sample selectors

_is_even_number

Returns an anonymous subroutine that returns true it's argument is an even number, and return the empty list otherwise.

The anonymous subroutine takes a hash reference as an argument and tests the value with the key field.

_is_odd_number

Returns an anonymous subroutine that returns true if it's argument is odd, and return the empty list otherwise.

The anonymous subroutine takes a hash reference as an argument and tests the value with the key field.

_is_tuesday

Returns an anonymous subroutine that returns true if the system time indicates it's Tuesday, and return the empty list otherwise.

Selector factories

sub __normalize_var_name { my $field = shift;

        $field =~ s/\W/_/g;

        return $field;
        }
__field_has_string_value( FIELD, VALUE )
 =cut

sub __field_has_string_value { my( $bucket, $setup ) = @_;

        my $sub = sub {
                $_[0]->{ $setup->{field} } == $setup->{value} ? 1 : ();
                };


        $bucket->__field_has_value( $setup, $sub );
        }
__field_has_numeric_value( FIELD, VALUE )
 =cut

sub __field_has_numeric_value { my( $bucket, $setup ) = @_;

        my $sub = sub {
                $_[0]->{ $setup->{field} } == $setup->{value} ? 1 : ();
                };


        $bucket->__field_has_value( $setup, $sub );
        }

sub __field_has_value { my( $bucket, $setup, $sub ) = @_;

        my $sub_field = __normalize_var_name( $setup->{field} );
        my $sub_value = __normalize_var_name( $setup->{value} );

        my $bucket_class = Brick->bucket_class;

        my $method_name  = "_${sub_field}_is_${sub_value}";


        {
        no strict 'refs';
        *{$method_name} = $sub;
        }


        $bucket->add_to_bucket(
                {
                name        => $method_name,
                description => "Field [$$setup{field}] has value [$$setup{value}]",
                code        => $sub,
                }
                );

        }

TO DO

TBA

SEE ALSO

Brick::Composers

There are selectors in the examples in t/use_cases.

SOURCE AVAILABILITY

This source is in Github:

        https://github.com/briandfoy/brick

AUTHOR

brian d foy, <bdfoy@cpan.org>

COPYRIGHT

Copyright © 2007-2022, brian d foy <bdfoy@cpan.org>. All rights reserved.

You may redistribute this under the terms of the Artistic License 2.0.