# When to return an explicit \`nothing\` from a function?

**URL:** <https://discourse.julialang.org/t/when-to-return-an-explicit-nothing-from-a-function/41846>\
**Category:** Performance\
**Created:** [June 22, 2020, 8:35am UTC](https://discourse.julialang.org/t/when-to-return-an-explicit-nothing-from-a-function/41846 "2020-06-22T08:35:20Z")\
**Posts on this page:** 10\
**Page:** 1

<div class="post-metadata">

**Author:** ![robsmith11](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/robsmith11/32/29641_2.png) [@robsmith11](https://discourse.julialang.org/u/robsmith11)\
**Post date:** [June 22, 2020, 8:35am UTC](https://discourse.julialang.org/t/when-to-return-an-explicit-nothing-from-a-function/41846/1 "2020-06-22T08:35:21Z")

</div>

After making a few minor modifications to a function, I was surprised that my program went from a few hundred allocations to millions.

It turns out that even though I never used the return value of the function (the last line of the function was just pushing to a `StructArray`), it was somehow impacting the performance of my program. Adding `nothing` to the last line of the function cleared up all of the extra allocations.

Should I always be using `nothing` when I don’t intend to use the return value of a function?

---

<div class="post-metadata">

**Author:** ![JeffreySarnoff](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jeffreysarnoff/32/1980_2.png) [@JeffreySarnoff](https://discourse.julialang.org/u/JeffreySarnoff)\
**Post date:** [June 22, 2020, 8:47am UTC](https://discourse.julialang.org/t/when-to-return-an-explicit-nothing-from-a-function/41846/2 "2020-06-22T08:47:11Z")

</div>

Functions that have nothing to return and are written to return `nothing` are entirely reasonable. Sometimes, when writing a function that modifies the internal state of a vector, dict, or other indirectly passed data structure, people choose to return that data structure explicitly – so it is available for use in an assignment however that often is a matter of personal style rather than a logical requirement. In situations where returning `nothing` has no downside, and increases the performance or lessens memory use you should use `nothing` as the returned value.

When your function has no defined result or does not need to convey something back to the caller via assignment or other use of a returned value, it is best to return `nothing` as that is the state yielded that most informs your intent.

---

<div class="post-metadata">

**Author:** ![robsmith11](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/robsmith11/32/29641_2.png) [@robsmith11](https://discourse.julialang.org/u/robsmith11)\
**Post date:** [June 22, 2020, 8:56am UTC](https://discourse.julialang.org/t/when-to-return-an-explicit-nothing-from-a-function/41846/3 "2020-06-22T08:56:55Z")

</div>

That makes sense – using an explicit `nothing` makes the intent more clear. My surprise is more that the `nothing` is _required_ for good performance, even in cases where the return value of the function is never used. My expectation was that Julia would be smart enough to optimize that away.

A pseudocode example of where I wouldn’t expect the `nothing` to be required for good performance, but it apparently is:

```julia
function modify_state!(s::State)
 push!(s.v, (a=1, b=rand(), c=:foo))
 nothing # required for good performance
end

function run()
 s = init_state()
 modify_state!(s) # the return value is never used
 println("done")
end

```

---

<div class="post-metadata">

**Author:** ![GunnarFarneback](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/gunnarfarneback/32/1827_2.png) [@GunnarFarneback](https://discourse.julialang.org/u/GunnarFarneback)\
**Post date:** [June 22, 2020, 10:13am UTC](https://discourse.julialang.org/t/when-to-return-an-explicit-nothing-from-a-function/41846/4 "2020-06-22T10:13:10Z")

</div>

I haven’t run into this problem for quite some time now, but it’s not inconceivable that a stray return value could upset inference or confuse the code generation in other ways. If you have a clear and simple enough case it may be worth filing an issue; it is indeed a missed optimization.

Note that ending the function with `nothing`, `return nothing` or just `return` are all equivalent. Personally I prefer the latter but it’s a matter of taste.

---

<div class="post-metadata">

**Author:** ![jishnub](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jishnub/32/33620_2.png) [@jishnub](https://discourse.julialang.org/u/jishnub)\
**Post date:** [June 22, 2020, 11:33am UTC](https://discourse.julialang.org/t/when-to-return-an-explicit-nothing-from-a-function/41846/5 "2020-06-22T11:33:42Z")

</div>

Could you provide an example of this? I seem to find no obvious difference using vectors.

```julia
julia> function modify_state!(s::AbstractVector)
        push!(s,one(eltype(s)))
        nothing # required for good performance
       end

julia> function run()
        s = Int[]
        modify_state!(s) # the return value is never used
        s
       end

julia> function modify_state2!(s::AbstractVector)
        push!(s,one(eltype(s)))
       end

julia> function run2()
        s = Int[]
        modify_state2!(s) # the return value is never used
        s
       end

julia> @btime run(); @btime run2();
  80.253 ns (2 allocations: 128 bytes)
  79.752 ns (2 allocations: 128 bytes)

```

---

<div class="post-metadata">

**Author:** ![Henrique\_Becker](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/henrique_becker/32/15443_2.png) [@Henrique\_Becker](https://discourse.julialang.org/u/Henrique_Becker)\
**Post date:** [June 22, 2020, 11:56am UTC](https://discourse.julialang.org/t/when-to-return-an-explicit-nothing-from-a-function/41846/6 "2020-06-22T11:56:06Z")

</div>

> [@GunnarFarneback](#):
>
> Note that ending the function with `nothing` , `return nothing` or just `return` are all equivalent. Personally I prefer the latter but it’s a matter of taste.

[Relevant section of the Julia docs.](https://docs.julialang.org/en/v1/manual/functions/#Returning-nothing-1)

> If the return from a function is `nothing` , use `return` instead of `return nothing` .

[From the JuMP Style Guide.](https://jump.dev/JuMP.jl/v0.21/style/#Return-statements-1)

---

<div class="post-metadata">

**Author:** ![robsmith11](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/robsmith11/32/29641_2.png) [@robsmith11](https://discourse.julialang.org/u/robsmith11)\
**Post date:** [June 22, 2020, 12:34pm UTC](https://discourse.julialang.org/t/when-to-return-an-explicit-nothing-from-a-function/41846/7 "2020-06-22T12:34:23Z")

</div>

Thanks, I’ll use `return` from now on.

Unfortunately, I wasn’t able to get a minimal reproducer to show the same behavior. There were two functions in my project though that consistently exhibit this behavior. One of them is the following:

```julia
function remove_order!(s::St, id::Id, px::Px)
 buy = id > 0
 ob = ifelse(buy, s.bids, s.asks)
 ir = searchsorted(ob.px, px, rev=buy)
 i = findfirst(x->x==id, view(ob.id, ir))
 if isnothing(i)
  error("Tried to remove missing order with id: $id and px: $px")
 else
  deleteat!(ob, ir[1] + i-1)
 end
 s.stats && push!(s.stats1, (a=sbestask(s), b=sbestbid(s), id=id, filled=false, open=false, px=px, qty=Qty(0), t=s.lastTime))
 nothing
end

```

Removing the `nothing` causes total allocations to go from 350 to 4.3 million. `s.stats1` is a StructArray of named tuples with isbits field types.

---

<div class="post-metadata">

**Author:** ![robsmith11](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/robsmith11/32/29641_2.png) [@robsmith11](https://discourse.julialang.org/u/robsmith11)\
**Post date:** [June 22, 2020, 1:06pm UTC](https://discourse.julialang.org/t/when-to-return-an-explicit-nothing-from-a-function/41846/8 "2020-06-22T13:06:51Z")

</div>

Ok, I’ve found a minimal reproducer:

```julia
julia> function f(b, sa)
        b && push!(sa, (a=rand(),))
        return
       end
f (generic function with 7 methods)

julia> function g()
        sa = StructArray{typeof((a=0.0,))}(undef, 0)
        for _ in 1:10^6
         f(true, sa)
        end
        return
       end
g (generic function with 5 methods)

julia> @btime g()
  10.207 ms (20 allocations: 9.00 MiB)

julia> function f(b, sa)
        b && push!(sa, (a=rand(),))
        # return
       end
f (generic function with 7 methods)

julia> @btime g()
  13.307 ms (1000020 allocations: 24.26 MiB)

```

---

<div class="post-metadata">

**Author:** ![Elrod](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/elrod/32/22461_2.png) [@Elrod](https://discourse.julialang.org/u/Elrod)\
**Post date:** [June 22, 2020, 1:11pm UTC](https://discourse.julialang.org/t/when-to-return-an-explicit-nothing-from-a-function/41846/9 "2020-06-22T13:11:25Z")

</div>

Check the return types of both versions.  
Original is not type stable, because the return type depends on the value of `b`.  
This should also fix the allocations:

```julia
b ? push!(sa, (a=rand(),)) : (a = 0.0,)

```

Although I’d prefer the `return` version.

---

<div class="post-metadata">

**Author:** ![robsmith11](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/robsmith11/32/29641_2.png) [@robsmith11](https://discourse.julialang.org/u/robsmith11)\
**Post date:** [June 22, 2020, 1:15pm UTC](https://discourse.julialang.org/t/when-to-return-an-explicit-nothing-from-a-function/41846/10 "2020-06-22T13:15:28Z")

</div>

Ahh… you’re right!

I think I’ll still get in the habit of using `return` when I don’t intend to return anything to avoid these cases in the future.
