How to Repeat a Function N Times

How do I call a function twice or more times consecutively?

I would:

for _ in range(3):
do()

The _ is convention for a variable whose value you don't care about.

You might also see some people write:

[do() for _ in range(3)]

however that is slightly more expensive because it creates a list containing the return values of each invocation of do() (even if it's None), and then throws away the resulting list. I wouldn't suggest using this unless you are using the list of return values.

Applying a function n times

In the first line of your code: you say "I declare a function called n_times that take a triplet (f, n, v) so one argument" then at the call site (third line) you give 3 arguments.

To fix this: write let rec n_times f n v = on line 1 or n_times (f, n-1, (f v)) on line 3.

How to repeat a function call n times

Lets take a look at a similar function.

(define (repeat-exp fn ct)
(if (= ct 1)
fn
(repeat `(lambda (x) (,fn x)) (- ct 1))))

Calling it will get you

> (repeat-exp inc 5)
'(lambda (x)
((lambda (x)
((lambda (x)
((lambda (x)
((lambda (x)
(#<procedure:inc> x))
x))
x))
x))
x))
>

As you can see, your initial function only gets called once; in the innermost evaluation. If you want it to get called at each level, you need to call it there too.

(define (repeat-exp2 fn ct)
(if (= ct 1)
fn
`(lambda (x)
(,fn (,(repeat-exp2 fn (- ct 1)) x)))))

> (repeat-exp2 inc 5)
'(lambda (x)
(#<procedure:inc>
((lambda (x)
(#<procedure:inc>
((lambda (x)
(#<procedure:inc>
((lambda (x)
(#<procedure:inc>
(#<procedure:inc> x)))
x)))
x)))
x)))
>

Now you can write the numeric equivalent.

(define (repeat2 fn ct)
(if (= ct 1)
fn
(lambda (x)
(fn ((repeat2 fn (- ct 1)) x)))))

which should do what you wanted initially.

> (repeat2 inc 5)
#<procedure>
> ((repeat2 inc 5) 2)
7

Repeat a function N times in Julia (composition)

The solution with ntuple and splatting works very well up to a certain number of compositions, say 10, and then falls off a performance cliff.

An alternative solution, using reduce, is fast for large numbers of compositions, n, but comparatively slow for small numbers:

compose_(f, n) = reduce(∘, ntuple(_ -> f, n))

I think that the following solution is optimal for both large and small n:

function compose(f, n)
function (x) # <- this is syntax for an anonymous function
val = f(x)
for _ in 2:n
val = f(val)
end
return val
end
end

BTW: it is the construction of the composed function which is faster in the approach suggested here. The runtimes of the resulting functions seem to be identical.



Related Topics



Leave a reply



Submit