Reputation: 8153
I'm trying to figure out how to return a function in Python. However, I don't know if the issue is with reduce
or with my code. What I currently have is this:
def combine(*args):
from functools import reduce
def closure(val):
return reduce( (lambda x, f: f(x)), args, val)
return closure
def first(array):
return array[0]
def shift(array):
return array[1:]
fifth = combine(first, shift, shift, shift, shift)
print(fifth([1,2,3,4,5,6,7,8,9]) # should return 5
However, I get the error message:
TypeError: 'int' object is not subscriptable
What's causing this?
Upvotes: 0
Views: 250
Reputation: 40804
As it is defined in your question, fifth(x)
is the same as:
fifth(x) = shift(shift(shift(shift(first(x)))))
Now, if x = [1,2,3,4,5,6,7,8,9]
, then
first(x) = 1
But that means that
shift(first(x)) = first(x)[1:] = 1[1:]
But as the error message tells us, 1
is not subscriptable.
I assume what's really causing this is a misconception about the order reduce
works. It works from left to right, so the leftmost function given is applied first (i.e., innermost):
combine(a, b, c)(x) = c(b(a(x)))
If you instead wanted a(b(c(x)))
, you would have to either pass them to combine
in the reverse order, or modify your defintion of combine
so that it reverses the order of the arguments for you:
def combine(*args):
from functools import reduce
def closure(val):
return reduce( (lambda x, f: f(x)), reversed(args), val)
return closure
Upvotes: 2