Defining Functions within Function in Julia
It is good practice to avoid writing long functions where the same results obtain using a few smaller functions alongside a less small function. Julia does not impose a performance penalty when running well-crafted code designed that way.
In practice, small external functions are used much more often than are small internal subfunctions. Where it serves to simplify the internal organization of the implementation or otherwise makes it easier for others to follow, and the subfunction is small, go right ahead. Otherwise, [perhaps refactor your logic to avoid stand alone functions that presuppose the internal context of another function's implementation] and provide that additional functionality outside.
You usually only define a function inside another function if you want to return a closure. A closure is a function with some data associated to it. When you return a function from a function, the returned (inner) function "captures" the variables that are defined in the same local function scope in which the inner function is defined. Here is an example of the use of closures:
julia> function make_adder(amount)
function add(x)
return x + amount
end
end;
julia> add_one = make_adder(1);
julia> add_two = make_adder(2);
julia> 10 |> add_one
11
julia> 10 |> add_two
12
Notice that the function returned by make_adder
captures the value of amount
, which is provided as an argument to make_adder
.
It works equally well to return an anonymous function:
julia> function make_adder(amount)
return x -> x + amount
end;
julia> add_three = make_adder(3);
julia> 10 |> add_three
13
There can sometimes be performance issues with closures in Julia. If necessary, the performance issues can be addressed with FastClosures.jl.
Here are a couple more examples of closures:
julia> function make_counter()
x = 0
return () -> (x = x + 1; x)
end;
julia> counter = make_counter();
julia> counter()
1
julia> counter()
2
julia> counter()
3
julia> function numerical_derivative(f, dx)
function dfdx(x)
(f(x + dx) - f(x)) / dx
end
end;
julia> numerical_sine_derivative = numerical_derivative(sin, 0.1);
julia> numerical_sine_derivative(0) # Derivative of sin(x) at 0 equals 1
0.9983341664682815