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