# Boxing obvious cases where the type is clear

**URL:** <https://discourse.julialang.org/t/boxing-obvious-cases-where-the-type-is-clear/107192>\
**Category:** Performance\
**Created:** [December 6, 2023, 3:25am UTC](https://discourse.julialang.org/t/boxing-obvious-cases-where-the-type-is-clear/107192 "2023-12-06T03:25:37Z")\
**Posts on this page:** 1\
**Showing post:** 10

<div class="post-metadata">

**Author:** ![Benny](https://avatars.discourse-cdn.com/v4/letter/b/49beb7/32.png) [@Benny](https://discourse.julialang.org/u/Benny)\
**Post date:** [December 6, 2023, 10:56am UTC](https://discourse.julialang.org/t/boxing-obvious-cases-where-the-type-is-clear/107192/10 "2023-12-06T10:56:46Z")

</div>

> [@feribg](#):
>
> In pretty much every other programming language this will be a clear stack allocation

[Not so for closures](https://en.wikipedia.org/wiki/Closure_(computer_programming)#Implementation_and_theory), which is what you’re doing here. An excerpt from the link:

> A language implementation cannot easily support full closures if its run-time memory model allocates all automatic variables on a linear stack. In such languages, a function’s automatic local variables are deallocated when the function returns. However, a closure requires that the free variables it references survive the enclosing function’s execution. Therefore, those variables must be allocated so that they persist until no longer needed, typically via heap allocation, rather than on the stack, and their lifetime must be managed so they survive until all closures referencing them are no longer in use.

It might appear that the `do` block closure only executes within the enclosing function’s scope and thus does not need to allocate outside its stack, but in general a higher order function could cache the closure somewhere that outlives the scope, so there’s no way around this.

The type inference limitation is orthogonal to and would arise under [both static and dynamic typing](https://erik-engheim.medium.com/dynamically-typed-languages-are-not-what-you-think-ac8d1392b803). I’ve written about this [before](https://discourse.julialang.org/t/can-someone-explain-closures-to-me/105605/2) but long story short, it’s obviously impossible to infer a finite set of types for a captured variable that is reassigned by a closure because a method can be compiled for infinitely many call signatures and thus assign instances of infinitely many types to the captured variable. Hypothetically it’s possible that a typed box can be used for the variables you annotated, but right now it’s stored in an untyped `Core.Box`, and type conversions and assertions are inserted to enforce its annotated type.

For now, there’s a couple things you can do.

1. Refactor to storing the captured data in `Ref{T}` and mutate that instead of reassigning the variable directly. If you don’t ever reassign the variable, the captured variable will be inferred as `Ref{T}` and the contents inferred as `T`. This isn’t conceptually different from annotating and reassigning the variable, but it’s better than a `Core.Box` surrounded by type conversions and assertions.

1. Refactor so the variables aren’t captured, but provided to the closure as arguments. It could be easier to avoid unintended captures if you wrote a globally scoped function to pass into `open` instead of a locally scoped closure via `do` block. This is probably the cleaner option given how large and nested these `do` blocks are.

---

_[View the full topic](https://discourse.julialang.org/t/boxing-obvious-cases-where-the-type-is-clear/107192)._
