'lifting functions in python

Say you have a function f:integers -> integers, one should be able to lift this function to act on sets of integers.

I.e. f:sets of integers -> sets of integers, by f({a,b,...}) = {f(a),f(b),...}

How can one do this succinctly in python? That is, not involving iterables (loops), potentially something more native and order-independent.

I would expect f({a,b,...}) to be the syntax, but it's not. Maybe something like act(f,{a,b,...})?



Solution 1:[1]

Python 2.7.10

What you described is mapping; it does involve loops in the background, but it achieves your succinctness. Here's an example.

l = [1,2,3]   

#f returns n^2
def f(n):
    return n*n

l = map(f, l) #[1,4,9]

map applies the function f to every element of l.

map also works on sets; however, map returns back a list of values e.g. f({x1,x2,x3}) = [f(x1),f(x2),f(x3)], in an arbitrary order. You can turn the returned list back into a set by wrapping it as a set.

Python 3.6

In Python 3.6, map returns back a map object, and you will need to convert it to your desired typed. This example shows the map object converted to a list.

l = [1,2,3]
def f(n):
    return n*n
l = list(map(f, l)) #[1,4,9]

Alternatively, you can reduce the amount of code further using lambda functions, making it more succinct.

l = [1,2,3]
l = map(lambda x:x*x, l)

Where the lambda expression has the functionality f but used only there and non-existent afterwards.

Solution 2:[2]

The tools you want are map, and in itertools.

For example, to apply f on a collection c of elements, you can use

map(f, c)

Note that the application is lazy in Python 3, and eager in Python 2.7. Alternatively, you can also use a lazy comprehension:

g(f(x) for x in c)

Solution 3:[3]

You can pass multiple arguments as well , like this:

def square(*args) :
    l = []
    for i in args:
        l.append(i**2)
    return l

It'll return like:

>>>> square(1,2,3,4)
>>>> [1,2,9,16]
>>>> square(1)
>>>> [1]
>>>> square(1,6)
>>>> [1,36]

Solution 4:[4]

In Python currying is not a native feature but you can emulate it using functools.partial. For instance, you can use partial to lift a function f: A -> B to a function f': [A] -> [B].

from functools import partial
def f(...):
    ...

# lift f
f_lifted = partial(map, f)

Solution 5:[5]

from funcy import curry



def lift(fn):
    return curry(map)(fn)

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2 James Lim
Solution 3 Ubdus Samad
Solution 4 Omni
Solution 5 lo tolmencre