Evaluate multi-variable anonymous function for one variable

As @mauro3 suggested, all you need to do is create a new anonymous function for each of your g_i, where each anonymous function takes only one argument (x_i) and stores the appropriate values of the other arguments to f. A function with some of its arguments already bound to values is a closure and we usually write them in Julia with anonymous functions.

For example, given f(x, y), we can make g1 an anonymous function that only takes x and holds a default value for y:

julia> f(x, y) = x + y
f (generic function with 1 method)

julia> g1 = x -> f(x, 2.0)  # y = 2.0
(::#1) (generic function with 1 method)

julia> g2 = y -> f(1.5, y)  # x = 1.5
(::#3) (generic function with 1 method)

julia> g1(1.5) == g2(2.0) == f(1.5, 2.0)
true

To automate this across all the inputs to some function f, we just need to build up those anonymous functions in a loop.

Here’s one way to do it. I’m using the helpful setindex function from StaticArrays.jl to make this a bit more efficient:

julia> using StaticArrays: setindex

julia> function make_closures(f, default_values...)
         [xi -> f(setindex(default_values, xi, i)...) for i in 1:length(default_values)]
       end
make_closures (generic function with 1 method)

julia> gs = make_closures(f, 0.75, 1.5, 0.8)
3-element Array{##11#13{Int64,#f,Tuple{Float64,Float64,Float64}},1}:
 #11
 #11
 #11

julia> gs[1](1.0) == f(1.0, 1.5, 0.8)
true

julia> gs[2](1.0) == f(0.75, 1.0, 0.8)
true

julia> gs[3](1.0) == f(0.75, 1.5, 1.0)
true

A very nice feature of Julia is that you can do this with essentially no performance penalty. Using BenchmarkTools.jl:

julia> using BenchmarkTools

julia> @btime $(gs[1])(0.75)
  14.931 ns (0 allocations: 0 bytes)

Also, as @mauro3 suggested, it will be easier for us to read your code and help you if you quote it properly

2 Likes