"inline" variable in closure

I have a some function depending on an independent variable and some general parameters. In a simplified version

f(a, x) = a + x

where a is some complicated struct of parameters which I ideally would like to type only once. from a type stability stand point this is perfectly fine:

@code_warntype f(1.0, 1.0)
MethodInstance for f(::Float64, ::Float64)
  from f(a, x) in Main at REPL[3]:1
Arguments
  #self#::Core.Const(f)
  a::Float64
  x::Float64
Body::Float64
1 ─ %1 = (a + x)::Float64
└──      return %1

However, I need to shove this function into another function which only accepts one parameter [In this case it’s `nlsolve` from `NLsolve but I don’t think this is very relevant]. The usual way in another programming language would be to make a another closure like this:

a = 1
g(x) = f(a, x)

which is however not type stable and slow as shown by the Any in the return type:

@code_warntype g(1.0)
MethodInstance for g(::Float64)
  from g(x) in Main at REPL[5]:1
Arguments
  #self#::Core.Const(g)
  x::Float64
Body::Any
1 ─ %1 = Main.f(Main.a, x)::Any
└──      return %1

If I do

h(x) = 1.0 + x

I again something type stable

@code_warntype h(1.0)
MethodInstance for h(::Float64)
  from h(x) in Main at REPL[7]:1
Arguments
  #self#::Core.Const(h)
  x::Float64
Body::Float64
1 ─ %1 = (1.0 + x)::Float64
└──      return %1

How can I define a g(x) that lowers to the same code as h(x) but ideally without spelling the literal value of a in its body?

Write the code inside a function. The problem with g(x) = f(a, x) is simply that a is a (non-const) global. e.g.

function foo(a)
    g(x) = f(a, x)
    # ... do something with g ... 
end

Instead of a function, you can also use a let block, e.g.

let a=1
    g(x) = f(a,x)
    # ... do something with g ...
end

but functions are more flexible, and in general it’s best to get out of the habit of writing your code in the form of scripts full of global variables.

2 Likes

thank you!