1

I need to create a recursive function repeat which takes in a function and uses the function n number of times with the value of x. Here's an iterative version that explains my issue a bit more in detail.

def repeat(fn, n, x):
    res = x
    for i in range(n):
        res = fn(res)
        print(res)
    return res

print(repeat(lambda x: x**2, 3, 3)) returns 6561

First it takes 3^2, then 3^2^2 which is 81 then again 3^2^2^2 = 6561. How can i make this recursive so it can work like this.

square_three_times = repeat(lambda x: x**2, 3)
print(square_three_times(3)) return 6561

I have tried something like this but im really lost and not sure what to do.

def repeat(fn, n):
    if n == 1:
        return fn(n):
    else:
        def result(x):
            return fn(n)
    return repeat(fn,result(x))

This obviously wouldnt work since the recursion would keep going forever. But im not sure how i should write this code since i first need to calculate 3^2 before taking the next step 9^2 and so on.

10
  • Do you need to make it recursive, or do you need it to work like that? Recursion doesn’t have to be involved. Commented Dec 23, 2013 at 21:48
  • I need it to be recursive yes Commented Dec 23, 2013 at 21:49
  • Why aren't you using the x parameter for your recursive variant? Commented Dec 23, 2013 at 21:49
  • If you want a function that only does the repetition implement repeat(fn, n, x) and use functools.partial to implement the currying. Commented Dec 23, 2013 at 21:52
  • 1
    Note that in Python 3.3 the given example in your question returns 81. Commented Dec 23, 2013 at 22:31

2 Answers 2

4

First, you've got the base case wrong:

if n == 1:
    return fn

After all, repeat(fn, 1) is just a function that applies fn once—that's fn.

Now, if the base case is when n == 1, the recursive case is almost always going to be something where you pass n - 1 to yourself.

So, what's the difference between repeat(fn, n) and repeat(fn, n-1)? If you can't figure it out, expand a simple case out in your head or on paper:

repeat(fn, 3)(x): fn(fn(fn(x)))
repeat(fn, 2)(x): fn(fn(x))

And now it's obvious: repeat(fn, n) is the same thing as fn(repeat(fn, n-1)), right? So:

else:
    def new_fn(x):
        return fn(repeat(fn, n-1)(x))
    return new_fn

However, as filmor points out in the comments, it would be easier to use partial here:

def repeat3(fn, n, x):
    if n == 1:
        return fn(x)
    else:
        return fn(repeat3(fn, n-1, x))

def repeat(fn, n):
    return functools.partial(repeat3, fn, n)
Sign up to request clarification or add additional context in comments.

1 Comment

Thanks im trying to use your first example but i get invalid syntax on return fn, i edited my original post. EDIT: Never mind, found my silly misstake.
-1

You can define this very simply in terms of your old repeat function:

repeat_new = lambda fn, n: lambda x: repeat(fn, n, x)

square_three_times = repeat_new (lambda x: x**2, 3)
print(square_three_times(3))

3 Comments

Yes, but that's not recursive, and the whole point of his question is how to do it recursively. (Plus, that's just a more verbose way of writing partial.)
@abarnert: functool.partial only gives you one level of partiality, doesn't it? Is there any easy way with partial to turn f(x, y, z) into g(x)(y)(z), instead of using g = lambda x: lambda y: lambda z: f(x, y, z)
That's like saying that lambda only lets you write one level of partiality explicitly… You can always call partial on a partial.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.