I wanted to learn about using map in python and a google search brought me to http://www.bogotobogo.com/python/python_fncs_map_filter_reduce.php which I have found helpful.
One of the codes on that page uses a for loop and puts map within that for loop in an interesting way, and the list used within the map function actually takes a list of 2 functions. Here is the code:
def square(x): 
    return (x**2)
def cube(x):
    return (x**3)
funcs = [square, cube]
for r in range(5):
    value = map(lambda x: x(r), funcs)
    print value
output:
[0, 0]
[1, 1]
[4, 8]
[9, 27]
[16, 64]
So, at this point in that tutorial, I thought "well if you can write that code with a function on the fly (lambda), then it could be written using a standard function using def". So I changed the code to this:
def square(x): 
    return (x**2)
def cube(x):
    return (x**3)
def test(x):
    return x(r)
funcs = [square, cube]
for r in range(5):
    value = map(test, funcs)
    print value
I got the same output as the first piece of code, but it bothered me that variable r was taken from the global namespace and that the code is not tight functional programming. And there is where I got tripped up. Here is my code:
def square(x): 
    return (x**2)
def cube(x):
    return (x**3)
def power(x):
    return x(r)
def main():
    funcs = [square, cube]
    for r in range(5):
        value = map(power, funcs)
        print value
if __name__ == "__main__":
    main()
I have played around with this code, but the issue is with passing into the function def power(x). I have tried numerous ways of trying to pass into this function, but lambda has the ability to automatically assign x variable to each iteration of the list funcs.
Is there a way to do this by using a standard def function, or is it not possible and only lambda can be used? Since I am learning python and this is my first language, I am trying to understand what's going on here.
You could nest the power() function in the main() function:
def main():
    def power(x):
        return x(r)
    funcs = [square, cube]
    for r in range(5):
        value = map(power, funcs)
        print value
so that r is now taken from the surrounding scope again, but is not a global. Instead it is a closure variable instead.
However, using a lambda is just another way to inject r from the surrounding scope here and passing it into the power() function:
def power(r, x):
    return x(r)
def main():
    funcs = [square, cube]
    for r in range(5):
        value = map(lambda x: power(r, x), funcs)
        print value
Here r is still a non-local, taken from the parent scope!
You could create the lambda with r being a default value for a second argument:
def power(r, x):
    return x(r)
def main():
    funcs = [square, cube]
    for r in range(5):
        value = map(lambda x, r=r: power(r, x), funcs)
        print value
Now r is passed in as a default value instead, so it was taken as a local. But for the purposes of your map() that doesn't actually make a difference here.
Currying is another option. Because a function of two arguments is the same as a function of one argument that returns another function that takes the remaining argument, you can write it like this:
def square(x):
    return (x**2)
def cube(x):
    return (x**3)
def power(r):
    return lambda(x): x(r) # This is where we construct our curried function
def main():
    funcs = [square, cube]
    for y in range(5):
        value = map(power(y), funcs) # Here, we apply the first function
                                     # to get at the second function (which
                                     # was constructed with the lambda above).
        print value
if __name__ == "__main__":
    main()
To make the relation a little more explicit, a function of the type (a, b) -> c (a function that takes an argument of type a and an argument of type b and returns a value of type c) is equivalent to a function of type a -> (b -> c).
If you want to get a little deeper into the math behind this equivalence, you can see this relationship using a bit of algebra. Viewing these types as algebraic data types, we can translate any function a -> b to ba and any pair (a, b) to a * b. Sometimes function types are called "exponentials" and pair types are called "product types" because of this connection. From here, we can see that
c(a * b) = (cb)a
and so,
(a, b) -> c  ~=  a -> (b -> c)
                        If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With