I have some predicates, for example:
is_divisible_by_13 = lambda i: i % 13 == 0 is_palindrome = lambda x: str(x) == str(x)[::-1]
and you want to logically combine them, as in:
filter(lambda x: is_divisible_by_13(x) and is_palindrome(x), range(1000,10000))
The question arises: can such a combination be written in the style of pointfree , for example:
filter(is_divisible_by_13 and is_palindrome, range(1000,10000))
This, of course, is not the desired effect, because the truth value of the lambda functions True and and and or are short-circuit operators. The closest I came up with is to define a class P , which is a simple predicate container that implements __call__() and has the and_() and or_() methods for combining predicates. The definition of P as follows:
import copy class P(object): def __init__(self, predicate): self.pred = predicate def __call__(self, obj): return self.pred(obj) def __copy_pred(self): return copy.copy(self.pred) def and_(self, predicate): pred = self.__copy_pred() self.pred = lambda x: pred(x) and predicate(x) return self def or_(self, predicate): pred = self.__copy_pred() self.pred = lambda x: pred(x) or predicate(x) return self
With P I can now create a new predicate, which is a combination of predicates like this:
P(is_divisible_by_13).and_(is_palindrome)
which is equivalent to the above lambda function. This comes close to what I would like to have, but it is also not meaningless (the points are now the predicates themselves, and not their arguments). Now the second question: is there a better or shorter way (perhaps without parentheses and dots) to combine predicates in Python than using classes like P and without using (lambda functions)?
python function-composition pointfree predicate
Frank S. Thomas
source share