Tutorial 3: using match_p
The match_p was introduced with version 0.9 of py-predicate. It’s a regular expression implementation with a twist: instead of using a regex on a string, you can use regular expressions with predicates, applied to any iterable. A few examples will make this more clear.
A minimal example
In this example we introduce the match_p
predicate.
We will define a matcher that matches an iterable on an int
, followed by a str
:
from predicate import match_p, is_int_p, is_str_p
predicate = match_p(is_int_p, is_str_p)
predicate([2]) # False
predicate([1, "foo"]) # True
match_p
accepts all the predicates (including match_p
itself!) defined in py-predicate,
and applies them one by one to the Iterable.
This is convenient, but the real power of his approach can be seen once we start using regex operators.
The optional
operator
This is an implementation of the ? (question mark) that indicates that either 0 or 1 matches of the predicate should evaluate to True.
In this example we want to match a list that should start with zero or one integers, followed by a string:
from predicate import match_p, is_int_p, is_str_p, optional
maybe_int = optional(is_int_p)
predicate = match_p(maybe_int, is_str_p)
predicate([2]) # False
predicate(["foo"]) # True
predicate([1, "foo"]) # True
predicate([1, 2, "foo"]) # False
The star
operator
This is an implementation of the * (asterisk) that indicates that either 0 or more matches of the predicate should evaluate to True.
In this example we want to match a list that should start with zero or more integers, followed by a string:
from predicate import match_p, is_int_p, is_str_p, star
zero_or_more_ints = star(is_int_p)
predicate = match_p(zero_or_more_ints, is_str_p)
predicate([2]) # False
predicate(["foo"]) # True
predicate([1, "foo"]) # True
predicate([1, 2, "foo"]) # True
The plus
operator
This is an implementation of the + (polus) that indicates that either 1 or more matches of the predicate should evaluate to True.
In the following example we want to match on at least one integer, followed by at least one string:
from predicate import match_p, is_int_p, is_str_p, plus
one_or_more_ints = plus(is_int_p)
one_or_more_strings = plus(is_str_p)
predicate = match_p(one_or_more_ints, one_or_more_ints)
predicate([2]) # False
predicate(["foo"]) # False
predicate([1, "foo"]) # True
predicate([1, 2, "foo"]) # True
The repeat
operator
Sometimes you want to check for a range. In standard regular syntax this is indicated with curly brackets.
In the following example we match on an iterable starting with 2 or 3 integers, followed by a string:
from predicate import match_p, is_int_p, is_str_p, repeat
one_or_two_ints = repeat(2, 3, is_int_p)
predicate = match_p(one_or_two_ints, is_str_p)
predicate([1]) # False
predicate([1, "foo"]) # False
predicate([1, 2, "foo"]) # True
predicate([1, 2, 3, 4, "foo"]) # False