Timothée HENRY
Timothée HENRY

Reputation: 14614

Julia - generate an array of functions programmatically

I want to generate an array of functions programmatically, with a loop so that each successive function depends on the previous.

For example in pseudo-code:

f_array = [f1, f2, f3]
with:
f1(x) = x
f2(x) = 3 * f1(x)
f3(x) = 3 * f2(x)

so that I could call:
f_array[3](x)
and get the result of f3(x)

Here is what I have tried:

  # create simple function just to initialize
  f(x)=x
  
  # initialize array of functions
  N = 3
  f_array = fill(f, N)
  
  # now we update each function
  for i in 2:N
    f_array[i] = (f(x)= 3 * f_array[i-1](x))
  end

I get an error:

ERROR: MethodError: Cannot convert an object of type getfield(Main, Symbol("#f#15")){Int64} to an object of type typeof(f)

I cannot find a solution at the moment. Any help would be appreciated.

Upvotes: 1

Views: 1645

Answers (3)

phipsgabler
phipsgabler

Reputation: 20980

I'd write Yegor's answer as

f_array = Function[identity]
for i in 2:3
     push!(f_array, x -> 3f_array[i-1](x))
end

But more importantly, this is a well known pattern: iterated function application. And it is already implemented, not in Base, but for example in IterTools.jl, by which you should be able to write:

f_array(start, N) = collect(Iterators.take(iterated(x -> 3x, start), N))

(I didn't test this, though.)

Upvotes: 1

Timothée HENRY
Timothée HENRY

Reputation: 14614

In the mean time, I also found a way using metaprogramming. I post this here as it could be useful for others:

f1(x) = x

for i in 2:N
  prog = "f$i(x) = 3 * f$(i-1)(x)"
  exp = Meta.parse(prog)
  eval(exp)
end

f3(2)
# 18

Upvotes: 1

Yehor Androsov
Yehor Androsov

Reputation: 6152

When you use fill with f it sets expected type for the elements of f_array to f, in the code below I am switching to abstract type to make it possible to have any function in the array

  # create simple function just to initialize
  f(x)=x
  
  # initialize array of functions
  N = 3
  f_array = Array{Function}(undef, N);
  f_array[1] = f;

  # now we update each function
  for i in 2:N
    f_array[i] = x -> 3 * f_array[i-1](x)
  end

  print(f_array[3](2))

which produces a value of 18

Upvotes: 2

Related Questions