Skip to content

Instantly share code, notes, and snippets.

@jomido
Last active October 12, 2017 19:39
Show Gist options
  • Save jomido/8c3a6df9fef7345016c3c8a107595a1d to your computer and use it in GitHub Desktop.
Save jomido/8c3a6df9fef7345016c3c8a107595a1d to your computer and use it in GitHub Desktop.
Partial Application & Predicates (https://docs.python.org/3.6/howto/functional.html)

partial application

what

Partial application lets you lock in one or more arguments to a function. It gives you a new function that only takes the remaining, as-yet-to-be-specified arguments. If arguments are applied against a function, then partial application allows you to apply only some of them - that is, you can partially apply them. Later on, you can finish out the argument application.

One can also read the Python docs.

from functools import partial


def add(a, b):

    return a + b


add10 = partial(add, 10)


add10(1)  # 11

The add10 function above is equivalent to:

def add10(b):

    return add(10, b)

why

Consider a thing that can be configured and then used. The usual OO pattern is to create a class, like so:

class Thing:

    def __init__(self, some_parameter=''):

        self.some_parameter = some_parameter

    def do_the_thing(self, n):

        print(n * 'I am {}. '.format(self.some_parameter))


cool_thing = Thing(some_parameter="cool")
cool_thing.do_the_thing(2)  # 'I am cool. I am cool.'

hot_thing = Thing(some_parameter="hot")
hot_thing.do_the_thing(3)  # 'I am hot. I am hot. I am hot.'

But you could also try out partial application:

def do_the_thing(n, some_parameter=''):

    print(n * 'I am {}. '.format(some_parameter))

cool_thing = partial(do_the_thing, some_parameter="cool")
cool_thing(2)  # 'I am cool. I am cool.'

hot_thing = partial(do_the_thing, some_parameter="hot")
hot_thing(3)  # 'I am hot. I am hot. I am hot.'

from source

The Python implementation of partial application can be found here.

predicates

what

A predicate is a function that returns either True or False.

def is_cool(n):

    return 0 <= n < 10

Any time you use an "if" statement, you're evaluating a predicate expression:

if 0 >= n < 10:

    print('is cool')

You can create a predicate from any expression by wrapping it in a function or lambda:

is_cool = lambda n: 0 <= n < 10

if is_cool(n):

    print('is cool')

why

You can pass around predicates when they are wrapped in functions. You cannot pass around an expression. For instance:

numbers = range(-10, 20)
cool_numbers = filter(numbers, is_cool)

print(cool_numbers)  # [0, 1, 2 ..., 9]

You can throw predicates in a list and evaluate all of them:

is_very_cool = lambda n: 0 <= n < 100
is_odd = lambda n: n % 2 == 1
is_prime = lambda n: n > 1 and all(n % i for i in range(2, n))

predicates = lambda n: all(p(n) for p in (
    is_very_cool,
    is_odd,
    is_prime
))

numbers = range(-10, 200)
very_cool_odd_primes = filter(predicates, numbers)

print(very_cool_odd_primes)  # [3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41,
                             #  43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97]

Two "default" predicates that sometimes come in handy:

always = lambda *args, **kwargs: True
never = lambda *args, **kwargs: False

from source

You can see examples of predicate use in the Python repo on Github.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment