NAME
Data::Predicate::Predicates
SYNOPSIS
use Data::Predicate::Predicates qw(:all);
# we also support :logic :defaults :tests as groups for imports
my $predicate = p_and(p_defined(), p_is_number(), p_numeric_equals(1));
$predicate->apply(1); #Returns true
$predicate->apply(2); #Returns false
$predicate->apply(undef); #Returns false
$predicate->apply('a'); #Returns false
my @data = (1, 2, 3, 4, undef, 'a', 5, 1);
my $new_data = $predicate->filter(\@data);
#New data will == [1,1]
DESCRIPTION
Try using this class first before going off & building your own Predicate.
This module is a set of useful ready built predicates. All predicates defined here use Data::Predicate::ClosurePredicate
and build themselves by creating a closure and passing it into a constructor. Those which require no user input when calling the methods will be built when the class is first used. Otherwise the others have closures built on the fly to fit your needs.
If your logic is too complex for these predicates or too slow then build your own by using Data::Predicate
and implementing apply()
or by creating your own closure & an instance of Data::Predicate::ClosurePredicate
.
All methods are prefixed with a p_
to avoid problems with other modules importing into this name space and to avoid clashes with built-in homonyms.
EXPORT OPTIONS
all
Exports all methods into your scope
logic
Imports the logic operators p_and
, p_or
and p_not
defaults
Imports the p_always_true
and p_always_false
tests
Imports the methods not imported by logic or default tags. This means anything which is used to test a Perlism like blessed references.
SUBROUTINES/METHODS
p_and()
p_and(p_defined(), p_is_number())->apply(1) #Returns true
Combine multiple predicates into one predicate instance. The code iterates through all predicates and will exit the moment one predicate returns false.
p_or()
p_or(p_defined(), p_is_number())-apply('a') #Would return true because 'a' is defined
Combine multiple predicates into one predicate instance which will return the moment one predicate in the list returns true.
p_not()
p_or(p_defined())->apply(undef) #Returns true
Reverses the logic of the given predicate so the above really means return true if the object tested is undefined
p_always_true()
p_always_true()
Will always return true; useful for when you just want to pass everything
p_always_false()
Will always return false; useful for when you just want to fail everything
p_defined()
p_defined()->apply(1) #Returns true
Will only return true when the given value is defined
p_undef()
p_undef()->apply(undef) #Returns true
Will only return true when the given value is undefined
p_is_number()
p_is_number()->apply(1) #Returns true
Returns true if the given value is a number
p_blessed()
p_blessed()->apply(bless({})) #returns true
Returns true if the given value was a blessed value.
p_isa()
p_isa('My::Objs::Dog')->apply($dog) #Returns true if $dog was an extension of My::Objs::Dog
Returns true according to the rules of isa when called on an object. The predicate will also test to see if the object was a blessed one before calling isa.
This differs from most predicates as you must tell the method what kind of Object you are expecting. This is recorded in curried in a closure & then used during evaluation.
p_can()
p_can('howl')->apply($dog) #Returns true if $dog had a subroutine for howl()
Returns true if the given object could respond to the given subroutine message. The predicate assumes the reference must be blessed for it to find a subroutine via a reference.
This differs from most predicates as you must tell the method what kind of subrotuine you are expecting to find. This is recorded in curried in a closure & then used during evaluation.
p_ref_type()
p_ref_type('ARRAY')->apply([]) #Returns true if the given reference was what you originally said
Returns true if the given ref equalled the originally stated reference.
p_string_equals()
#Assume an object called Dog with the method howl which returns a string
p_string_equals('a')->apply('a') #returns true
p_string_equals('a')->apply('b') #returns false
#would return true if $dog had a subroutine called howl & it returned the specified string
p_string_equals('rrroouggghh', 'howl')->apply($dog)
Applies the eq test for strings. In it's basic form you can specify a String and it will only return true if the given value eq that String.
There is a more advanced mode which lets you call a subrotuine on the given reference and then evaluate the returned value. This allows you to use this subroutine with Objects rather than having to write a custom one for basic evaluation.
p_numeric_equals()
#Assume an object called Dog with the method age which returns a number
p_numeric_equals(1)->apply(1) #returns true
p_numeric_equals(1)->apply(2) #returns false
#would return true if $dog had a subroutine called age & it returned the specified number
p_numeric_equals(7, 'age')->apply($dog)
Applies the == test for numbers. In it's basic form you can specify a number and it will only return true if the given value == that number. Will also return false if it was given a String (which is passed into p_is_number())
There is a more advanced mode which lets you call a subrotuine on the given reference and then evaluate the returned value. This allows you to use this subroutine with Objects rather than having to write a custom one for basic evaluation.
p_regex()
#Assume an object called Dog with the method howl which returns a String
p_regex(qr/A/)->apply('Aaaa') #returns true
p_regex(qr/A/)->apply('bA') #returns true
p_regex(qr/A/)->apply('b') #returns false
p_regex(qr/rrr/, 'howl')->apply($dog) #Returns true if the string from howl matched /rrr/
Behaves identitcally to p_string_equals()
and p_numeric_equals()
allowing for basic regular expression matches using a compiled regex or by supplementing it with a subroutine to run the match on. This does not apply any numeric tests since it's quite valid to regex against a number. However it will return false if the value retrieved or evaluated was undefined.
p_substring()
p_substring('world')->apply('hello world'); #returns true
p_substring('o')->apply('hello world'); #returns true
p_substring('goodbye')->apply('hello world'); #returns false
#Again assume our Dog object returns arrooowww
p_substring('ooo', 'howl')->apply($dog);
This is another type of test which when looking for substrings is far more performant than using p_regex()
. The logic is to use your first variable as the substring to look for in the given value. If the index is greater than -1 we return true.
In micro-benchmarks we can see a 4x improvement in speed in using the substring style predicate over using regular expressions. Substring also has the advantage that you cannot have your substring mis-interpreted as a regular expression control character e.g. a period or braces
DEPENDENCIES
AUTHOR
Andrew Yates
LICENCE
Copyright (c) 2010 - 2010 European Molecular Biology Laboratory.
Author: Andrew Yates (ayatesattheebi - remove the relevant sections accordingly)
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. Neither the name of the Genome Research Ltd nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.