logankilpatrick
logankilpatrick

Reputation: 14521

Defining Functions within Function in Julia

I am wondering if there's any guidance out there about whether defining a function within a function is something recommended or to be avoided in Julia.

I read the Function section in the Julia Docs but did not see this topic mentioned.

A side note is that someone mentioned to me that this is a suggested behavior in Python which is what sparked this question in my mind.

Upvotes: 7

Views: 1907

Answers (2)

Cameron Bieganek
Cameron Bieganek

Reputation: 7674

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

Upvotes: 3

Jeffrey Sarnoff
Jeffrey Sarnoff

Reputation: 1757

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.

Upvotes: 2

Related Questions