18
votes

In Julia, I have a function for a complicated simulation, monte_carlo_sim() that involves many parameters. Inside this function, I need to call many other functions. I could write stand-alone functions outside of monte_carlo_sim(), but then I'd need to pass many parameters-- many of which are constant inside this function-- which would sacrifice elegance and clarity (and perhaps not take advantage of the fact that these are constant variables?). Is there a performance reason to not include functions within functions? As a toy example here, the temperature T is constant, and if I don't want to pass this variable to my function compute_Boltzmann(), I could do the following. Is there anything wrong with this?

function monte_carlo_sim(temp::Float64, N::Int)
    const T = temp

    function compute_Boltzmann(energy::Float64)
         return exp(-energy/T)
    end

    # later call this function many times
    for i = 1:1000
        energy = compute_energy()
        b = compute_Boltzmann(energy)
    end
end

Alternatively, I could define a new const type SimulationParameters and pass this to compute_Boltzmann instead, and writing compute_Boltzmann outside of the monte_carlo_sim function as here? Is this better? I'd be passing more information than I'd need in this case, though.

2

2 Answers

8
votes

Since google led me here, perhaps I add a comment:

Nested functions used to be slower, see for instance this discussion on github... in 2013. But not any more: running exactly the tests there on v0.6, they are all the same speed now.

This is still true for me if (like the question) the inner function implicitly depends on things defined within the outer function, which would have to be passed explicitly if it were a free-standing function.

3
votes

As you mentioned, code clarity is very important so you should focus on that on the first place. If you feel like functions within functions is your style and helps you (and your colleagues) understand your script better than do it. As for performance you can always compare the 2 implementations by using the @time macro. I wouldn't expect to see your functions within function implementation to suffer but it's always worth checking.

For more info on how to use @time and write high-performance code read the article here.