Defining functions which use other functions

ΔK(ϕ,λ,Δσ,a,c,Q,f) = λ(ϕ,a,c) * Δσ * sqrt(π * a / Q(a,c)) * f(ϕ)
dadN(λ,Δσ,a,c,Q,f) = ΔK(ϕ=90, ...)
  1. Should I include all functions, function inputs, and raw inputs in a higher level function signature, or is it better to just inherit some of these input values from scope?
    a. What’s the cutoff? Just have the function inherit all variables?
  2. Is the second line the right way to define a subset of some function?
  3. Is there a better way to name derivative variables like \frac{da}{dN}? Maybe a unicode fraction symbol that won’t be evaluated?

Looks good to me. For your second line, you’ll want args... instead of just ... to avoid a syntax error.

Also, you can avoid Q being an input, unless you want it to be a placeholder to pass different functions that take a, c as inputs. Same goes for f.

Maybe I’m misunderstanding, but let’s make a simpler example:

julia> f(a, b) = a/(a+b)

julia> g(a, b) = f(a, b)^2

julia> h(p, a, b) = p(a, b)^2

julia> f(1, 2)
0.3333333

julia> g(1, 2)
0.1111111

julia> h(f, 1, 2)
0.11111111

julia> h(+, 1, 2)
9

A function can simply use another function that is defined outside it (or indeed inside it but that’s for later). That’s what happens for g, it can just use f, no declarations needed.

If you need to be able to change which function is called inside your function, you can give it as an argument, like h does here. Putting the function argument first is a bit of a convention.

2 Likes

When it comes to inheriting variables from scope, this is called global variables and it’s a bit of a code smell, it will probably lower your performance. The exception is constants (like indeed those functions). If you notice you’re sending some constant into every function you may want to declare it a constant and remove it from the arguments.

1 Like

Isn’t it the case that for functions that take other functions as arguments, they should be defined annotating the types?

function z(p::F, a, b) where F
    p(a, b)^2
end

If you always want to specialize on the given function then yes. In your concrete example however I believe that Julia will anyway specialize on p, since you directly call p in the function body. See the performance docs for more info.

1 Like

Functions are automatically constants??

Also, won’t moving the functions to the front of the signature ruin the ability to use line 2?

Yes, f(x) = 3x is roughly equivalent to const f = x -> 3x.

I’m not sure what you mean by line 2. You can of course ignore the convention if you have some reason to do something else, the reason it exists is that there’s do-block syntax.
https://docs.julialang.org/en/v1/manual/functions/#Do-Block-Syntax-for-Function-Arguments