# Unexpected Core.Box from functions within a function

**URL:** <https://discourse.julialang.org/t/unexpected-core-box-from-functions-within-a-function/38022>\
**Category:** Performance\
**Created:** [April 22, 2020, 11:57am UTC](https://discourse.julialang.org/t/unexpected-core-box-from-functions-within-a-function/38022 "2020-04-22T11:57:04Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![mcabbott](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mcabbott/32/6603_2.png) [@mcabbott](https://discourse.julialang.org/u/mcabbott)\
**Post date:** [April 22, 2020, 11:57am UTC](https://discourse.julialang.org/t/unexpected-core-box-from-functions-within-a-function/38022/1 "2020-04-22T11:57:05Z")

</div>

I was surprised that something like the following is slow, and not type-stable:

```julia
function g(A)
    function make(A)
        B = similar(A)
        act!(B, A, axes(A, 1)) 
        B
    end
    function act!(B, A, ax)
        for i in ax
            B[i] = A[i] 
        end
    end
    B = make(A)
end

A = rand(3)
@code_warntype g(A) # Body::Any, act!@_4::Core.Box, B::Core.Box
@btime g($A) # 78.043 ns (5 allocations: 192 bytes)

```

This can be improved by avoiding re-using variable names. I just found [this thread from last year](https://discourse.julialang.org/t/inner-function-overhead/20394/2) which explains that assigning to `B` at the end causes the inner function’s `B` not to be a distinct variable. Which explains why this version is a bit better:

```julia
function g2(A2) # all names distinct, although B is sufficient
    function make2(A3)
        B3 = similar(A3)
        act2!(B3, A3, axes(A3, 1)) 
        B3
    end
    function act2!(B4, A4, ax4)
        for i in ax4
            B4[i] = A4[i] 
        end
        nothing
    end
    B2 = make2(A2)
end
@code_warntype g2(A) # Better, but still has act2!@_4::Core.Box
@btime g2($A) # 70.867 ns (4 allocations: 160 bytes)

```

However this still has a `Core.Box` around the inner function. Is this some variant of the closure bug/problem (although nothing is closed over)?

For comparison, the full-speed version is this:

```julia
function h(A) # with nothing nested
    B = similar(A)
    _act!(B, A, axes(A, 1)) 
    B
end
function _act!(B, A, ax)
    for i in ax
        B[i] = A[i] 
    end
end
@code_warntype h(A) # fine
@btime h($A) # 36.986 ns (1 allocation: 112 bytes)

```

---

<div class="post-metadata">

**Author:** ![tkf](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tkf/32/17635_2.png) [@tkf](https://discourse.julialang.org/u/tkf)\
**Post date:** [April 22, 2020, 4:03pm UTC](https://discourse.julialang.org/t/unexpected-core-box-from-functions-within-a-function/38022/2 "2020-04-22T16:03:44Z")

</div>

It seems re-assigning to the variable used for the name of the closure is allowed:

```julia
function demo()
    function f()
    end
    f = 1
    f
end

```

So, `function act2!` acts like an assignment, too. Using the “`let` hack” seems to fix the problem:

```julia
function g3(A2)
    function act2!(B4, A4, ax4)
        for i in ax4
            B4[i] = A4[i]
        end
        nothing
    end
    make2 = let act2! = act2!
        function make2(A3)
            B3 = similar(A3)
            act2!(B3, A3, axes(A3, 1))
            B3
        end
    end
    B2 = make2(A2)
end

```

---

<div class="post-metadata">

**Author:** ![mcabbott](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mcabbott/32/6603_2.png) [@mcabbott](https://discourse.julialang.org/u/mcabbott)\
**Post date:** [April 22, 2020, 4:25pm UTC](https://discourse.julialang.org/t/unexpected-core-box-from-functions-within-a-function/38022/3 "2020-04-22T16:25:03Z")

</div>

Oh I see now, the function `make` should be thought of as a closure over `act!`, which isn’t a constant because it is in local scope.

Thanks!

---

<div class="post-metadata">

**Author:** ![Vasily\_Pisarev](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/vasily_pisarev/32/7929_2.png) [@Vasily\_Pisarev](https://discourse.julialang.org/u/Vasily_Pisarev)\
**Post date:** [April 23, 2020, 6:21am UTC](https://discourse.julialang.org/t/unexpected-core-box-from-functions-within-a-function/38022/4 "2020-04-23T06:21:10Z")

</div>

In fact, just placing `act!` before `make` removes boxing on `act!`  
Declaring `B` as `local` inside `make` or using it in a `let` block

```julia
function make(A)
    let B = similar(A)
        act!(B, A, axes(A, 1))
        return B
    end
end

```

removes boxing on `B`.  
Btw, you don’t need to rename `B` in `act!`, because it’s bound there (`B` as argument name shadows `B` from the outer scope), and the same goes for `A` in both inner functions.

---

<div class="post-metadata">

**Author:** ![tkf](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tkf/32/17635_2.png) [@tkf](https://discourse.julialang.org/u/tkf)\
**Post date:** [April 23, 2020, 6:34am UTC](https://discourse.julialang.org/t/unexpected-core-box-from-functions-within-a-function/38022/5 "2020-04-23T06:34:14Z")

</div>

> [@Vasily\_Pisarev](#):
>
> In fact, just placing `act!` before `make` removes boxing on `act!`

Interesting. I was surprised a bit first but then I realized that it makes sense. Since `make` has to capture `act!` and make the closure object available right after the expression `function make ... end`, Julia has no choice but to create a box and fill it later.
