# How does compiler and other stuff works in closures

**URL:** <https://discourse.julialang.org/t/how-does-compiler-and-other-stuff-works-in-closures/134553>\
**Category:** New to Julia\
**Created:** [December 14, 2025, 10:18pm UTC](https://discourse.julialang.org/t/how-does-compiler-and-other-stuff-works-in-closures/134553 "2025-12-14T22:18:37Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![RCh](https://avatars.discourse-cdn.com/v4/letter/r/919ad9/32.png) [@RCh](https://discourse.julialang.org/u/RCh)\
**Post date:** [December 14, 2025, 10:18pm UTC](https://discourse.julialang.org/t/how-does-compiler-and-other-stuff-works-in-closures/134553/1 "2025-12-14T22:18:37Z")

</div>

Hi, another conceptual question.  
I have a closure like functionality:

```julia-auto
z = function outer1(x0::Int)
    x = x0
        function inner1()
            println(x)
        
        end

        function inner1(y::Int64)
            println(y)
        end
        
        return inner1

    end

```

Not sure if it works just only for Symbol type `z = :( function...`

I read in the documentation ( [Performance Tips · The Julia Language](https://docs.julialang.org/en/v1/manual/performance-tips/#The-dangers-of-abusing-multiple-dispatch-(aka,-more-on-types-with-values-as-parameters)) ) and as far as I understand it says for each of the type used in function, that whole process of creating some compiler methods and structure is needed.

I was thinking about it, and trying to make it lazy. So, the compiler “compiles” the code, only when it needs it. So, if the `z` is not called, the compiler doesn’t run/compile it, thus whole machinery around it is not executed.

How can I achieve something like this?

In the code above, where the push! and machinery code will be created, in the namespace of ‘z’ or in the global namespace?  
If in `z` namespace, if the garbage collector, will be called and `z` is candidate for cleaning, does the gc removes also the functions and `compiler's` related functionality?

How does it work with --trim?

---

<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 15, 2025, 3:31am UTC](https://discourse.julialang.org/t/how-does-compiler-and-other-stuff-works-in-closures/134553/2 "2025-12-15T03:31:35Z")

</div>

> [@RCh](#):
>
> Not sure if it works just only for Symbol type `z = :( function...`

`:()` isn’t part of the provided code, and `z =` isn’t necessary or typical.

> [@RCh](#):
>
> I was thinking about it, and trying to make it lazy. So, the compiler “compiles” the code, only when it needs it.

That’s already how Julia’s JIT compiler works.

> [@RCh](#):
>
> where the push! and machinery code will be created, in the namespace of ‘z’ or in the global namespace?

There’s no `push!` anywhere in your code. `z` is a variable, not a namespace. A function scope is also not a namespace. A namespace is a persistent container for names you can access; Julia has modules containing global variables.

> [@RCh](#):
>
> does the gc removes also the functions and `compiler's` related functionality?

Compiled method code does not ever go away, to my knowledge, it remains in older world ages. The garbage collector may remove the overlying function objects if they have no more references. `function outer1` assigns the function to a `const` name `outer1`, so it will always have a reference, even if only in an older world age. These are implementation details, not language specifications, so it could potentially change within v1.

---

<div class="post-metadata">

**Author:** ![RCh](https://avatars.discourse-cdn.com/v4/letter/r/919ad9/32.png) [@RCh](https://discourse.julialang.org/u/RCh)\
**Post date:** [December 15, 2025, 8:29pm UTC](https://discourse.julialang.org/t/how-does-compiler-and-other-stuff-works-in-closures/134553/3 "2025-12-15T20:29:47Z")

</div>

> [@Benny](#):
>
> That’s already how Julia’s JIT compiler works.

I was thinking, that some part of the code is in global namespace (I mean non-local), e.g. something related with macros?. Thus, does a function can be also in the global namespace?  
But I am not sure how can I be sure where it is put, cannot find some analogy similar to python (locals/globals) at least for interactive/REPL mode.

So, the whole idea was, that if the compiler compiles ,in some cases e.g: function, to global namespace, and based on documentation, it has to call whole machinery, then the compilation time can take a lot of time. Thus, I create some my own local namespaces with variables and via closures I return to appropriate method. =\> My namespace (hidden behind the variable) has limited impact of the global space, and also if the variable is not used anymore, my namespace and some related things to dynamic dispatch will be cleaned.

> [@Benny](#):
>
> There’s no `push!` anywhere in your code. `z` is a variable, not a namespace. A function scope is also not a namespace. A namespace is a persistent container for names you can access; Julia has modules containing global variables.

That was basically mentioned in the documentation, I know that it is not in the code. My apologise, I didn’t create own type. As I understand, that if you create some a new type, some `Base` functions for that types are also generated…(not sure)?

> [@Benny](#):
>
> Compiled method code does not ever go away, to my knowledge, it remains in older world ages. The garbage collector may remove the overlying function objects if they have no more references. `function outer1` assigns the function to a `const` name `outer1`, so it will always have a reference, even if only in an older world age. These are implementation details, not language specifications, so it could potentially change within v1.

Thank you!

---

<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 15, 2025, 10:09pm UTC](https://discourse.julialang.org/t/how-does-compiler-and-other-stuff-works-in-closures/134553/4 "2025-12-15T22:09:54Z")

</div>

I think you’re mixing a lot of things up, which is understandable because programming terminology is extremely vague and contextual. So I’ll explain it in terms typical for Julia users, and you need to understand that it can be different in other languages.

- The only namespace in the core Julia language is a module, and the names it holds are global variables. A module is also a global scope. Local scopes are not called namespaces, so if you want to distinguish global from local scopes, say scope.
- Scopes only contain names, also known as variables, not the objects the variables are assigned. We may refer to an object via an assigned variable, like the “`outer1` function in the global scope,” but that strictly means `outer1` is in the global scope and is assigned a function. This by the way is how Python works too; these are not languages where variables can be synonymous with owned objects.
- Where a function object, its methods, and compiled method code are stored is an implementation detail, not part of the language specification. Nested functions and closures don’t literally store functions inside another function, the placement is only about what variables their scopes can access. In the current implementation, the written definitions of the `outer1` and `inner1` methods added separate entries to one global method table, before any calls. The `outer1` function is assigned to the global `const` variable `outer1`, and `inner1` functions are instantiated by `outer1` calls, where the definitions are. If it sounds strange that `inner1` methods existed before its functions do, it should be known that the functions’ type was also made at definition and assigned a hidden global `const` variable, you can check `Base.return_types(outer1)` before any calls.
- The compiler does not approach globally defined methods and closures’ methods differently, though closures can access local variables that can be uninferrable in their own ways. There’s no point in making closures to optimize compilation, and it is completely unrelated to the Performance Tips section you linked about compiling for too many concrete and likely parametric types.

> [@RCh](#):
>
> - some part of the code is in global namespace (I mean non-local), e.g. something related with macros?
> - based on documentation, it has to call whole machinery
> - if the variable is not used anymore, my namespace and some related things to dynamic dispatch will be cleaned.
> - if you create some a new type, some `Base` functions for that types are also generated…(not sure)?

I have no idea where these ideas come from or what they could mean, I think you should just ignore it.
