# Get all names accessible from a Module

**URL:** https://discourse.julialang.org/t/get-all-names-accessible-from-a-module/98492
**Category:** General Usage
**Created:** [May 8, 2023, 4:05pm UTC](https://discourse.julialang.org/t/get-all-names-accessible-from-a-module/98492 "2023-05-08T16:05:16Z")
**Posts on this page:** 11
**Page:** 1

<div class="post-metadata">

### Author: ![disberd](https://avatars.discourse-cdn.com/v4/letter/d/8edcca/32.png) [@disberd](https://discourse.julialang.org/u/disberd)
#### Post date: [May 8, 2023, 4:05pm UTC](https://discourse.julialang.org/t/get-all-names-accessible-from-a-module/98492/1 "2023-05-08T16:05:16Z")

</div>

I know that `Base.names` can be used to extract most of the names that are accessible from inside a Module `m`, but I just realized that even if one calls it `names(m;all=true, imported=true)`, the list of returned names does not include the ones that are exposed inside `m` because of using other packages.

As an example suppose you have the following simple module definition

```julia
module TESTMODULE
using BenchmarkTools
end

```

calling `names(TESTMODULE;all=true, imported=true)` does not return any of the names exported by `BenchmarkTools`.

Is there a way to extract all of the variables/functions that are accessible from `TESTMODULE` above?

---

<div class="post-metadata">

### Author: ![Eben60](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/eben60/32/13475_2.png) [@Eben60](https://discourse.julialang.org/u/Eben60)
#### Post date: [October 7, 2023, 10:53am UTC](https://discourse.julialang.org/t/get-all-names-accessible-from-a-module/98492/2 "2023-10-07T10:53:38Z")

</div>

no one?

```julia
help?> names

  names(x::Module; all::Bool = false, imported::Bool = false)

  Get an array of the names exported by a Module, excluding deprecated names. If all is true, then the list also includes non-exported names defined in the
  module, deprecated names, and compiler-generated names. If imported is true, then names explicitly imported from other modules are also included.

```

Well, with `imported=true` you get not _all_ “names explicitly imported …” as I would normally read the docstring. But at least all imported/used modules are listed - thus you can then call

```julia
names(BenchmarkTools; all=false)

```

to get all names exported from `BenchmarkTools` and therefore imported into `TESTMODULE` (see also code below).

But what if we have a non-exported identifier explicitly imported?

```julia
module M0
f1(x) = x
f2() = "f2 available"
export f1
end

module M1
import ..M0
using ..M0: f2

nms = names(@ __MODULE__ , all=true, imported=true)
mods = [n for n in nms if getproperty(@ __MODULE__ , n) isa Module]
imported = vcat([names(getproperty(@ __MODULE__ , mod), all=false) for mod in mods]...)
allnames = union(nms, imported)
println(f2())
@show nms
@show imported
@show allnames
end

julia> 
f2 available
nms = [Symbol("#eval"), Symbol("#include"), :M0, :M1, :eval, :include]
imported = [:M0, :f1, :M1]
allnames = [Symbol("#eval"), Symbol("#include"), :M0, :M1, :eval, :include, :f1]

```

Any idea how to get `f2` listed?

Another question: the `names()` docstring doesn’t IMO reflect the behavior of the function. What is the intended behavior then?

---

<div class="post-metadata">

### Author: ![klwlevy](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/klwlevy/32/25272_2.png) [@klwlevy](https://discourse.julialang.org/u/klwlevy)
#### Post date: [October 7, 2023, 12:15pm UTC](https://discourse.julialang.org/t/get-all-names-accessible-from-a-module/98492/3 "2023-10-07T12:15:54Z")

</div>

How about this?

```julia
module M1
    import ..M0: f2
end

names(M1, imported=true)

```

 ![image](https://global.discourse-cdn.com/julialang/original/3X/c/0/c0d8ce23a7250ece9a43e8129c4d19ebbe162e8d.png)

---

<div class="post-metadata">

### Author: ![Eben60](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/eben60/32/13475_2.png) [@Eben60](https://discourse.julialang.org/u/Eben60)
#### Post date: [October 7, 2023, 2:16pm UTC](https://discourse.julialang.org/t/get-all-names-accessible-from-a-module/98492/4 "2023-10-07T14:16:39Z")

</div>

Thank you **klwlevy** , that worked. The difference between your code and mine is that I have the line

```julia
nms = names(@ __MODULE__ , all=true, imported=true)

```

within the module, and you call `names(M1, imported=true)` _after_ the execution of `M1`.

Unfortunately your suggestion doesn’t solve my problem, as I need the list of available identifiers “at the point of use”- within the module `M1`, and I do get all of them - except those explicitly imported.

---

<div class="post-metadata">

### Author: ![disberd](https://avatars.discourse-cdn.com/v4/letter/d/8edcca/32.png) [@disberd](https://discourse.julialang.org/u/disberd)
#### Post date: [October 7, 2023, 2:23pm UTC](https://discourse.julialang.org/t/get-all-names-accessible-from-a-module/98492/5 "2023-10-07T14:23:06Z")

</div>

@Eben60  
I think that here the issue is not whether you call the `names` function after module execution.

The example provided by @klwlevy works because he did `import ..M0: f2` rather than `using ..M0: f2`.

If you switch to using `import` it will also work and appear under the `nms` variable in your code.

The problem still remains that if variables are imported with `using` (explicitly or not) they can not be extracted with `names`

---

<div class="post-metadata">

### Author: ![Eben60](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/eben60/32/13475_2.png) [@Eben60](https://discourse.julialang.org/u/Eben60)
#### Post date: [October 7, 2023, 2:45pm UTC](https://discourse.julialang.org/t/get-all-names-accessible-from-a-module/98492/6 "2023-10-07T14:45:50Z")

</div>

**disberd** , thank you, you are correct on both points:

- That it is `import` vs `using` , not within vs. after
- and that doesn’t solve my problem.

It is even worse than I thought: The modules made available through `using` are completely “invisible” for the `names` function

```julia
module M4
using ..M0
end
println(names(M4, all=true, imported=true))

julia> 

[Symbol("#eval"), Symbol("#include"), :M4, :eval, :include]

```

Any ideas?

---

<div class="post-metadata">

### Author: ![klwlevy](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/klwlevy/32/25272_2.png) [@klwlevy](https://discourse.julialang.org/u/klwlevy)
#### Post date: [October 7, 2023, 7:36pm UTC](https://discourse.julialang.org/t/get-all-names-accessible-from-a-module/98492/7 "2023-10-07T19:36:00Z")

</div>

I probably don’t understand what your problem is.

Please state if this solves your problem or, alternatively, what you are lacking.  
It makes use of the package Reexport.jl.

```julia
module M0
    f1(x) = x
    f2() = "f2 available"
    f3(x) = sin(x)
    export f1, f3
end

module M1
    # This is a separate package
    using Reexport
    # Re-exporting exported symbols from M0 also in M1
    @reexport using ..M0
    # Re-exporting the non-exported symbol f2 from M0 in M1
    @reexport using ..M0: f2
end

M1.f1(42)
M1.f2()
M1.f3(3.14/2)
names(M1)

```

```julia
names(M1) = [:M0, :M1, :f1, :f2, :f3]

```

---

<div class="post-metadata">

### Author: ![Eben60](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/eben60/32/13475_2.png) [@Eben60](https://discourse.julialang.org/u/Eben60)
#### Post date: [October 7, 2023, 8:45pm UTC](https://discourse.julialang.org/t/get-all-names-accessible-from-a-module/98492/8 "2023-10-07T20:45:41Z")

</div>

Thank you @klwlevy, unfortunately that doesn’t solve my problem, which is

> I need the list of available identifiers “at the point of use”- within the module `M1`

without otherwise changing the code of the module (e.g. switching form `using` to `import` or `@reexport`), as that code is not mine.

This has to do with [this topic](https://discourse.julialang.org/t/workflow-with-redefining-structs/102982) : Upon wrapping a struct into a module through a macro I need to make the original context, or selected parts of it, available within this module. The problem is to obtain _all_ names in the original context.

---

<div class="post-metadata">

### Author: ![Eben60](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/eben60/32/13475_2.png) [@Eben60](https://discourse.julialang.org/u/Eben60)
#### Post date: [October 8, 2023, 9:28pm UTC](https://discourse.julialang.org/t/get-all-names-accessible-from-a-module/98492/9 "2023-10-08T21:28:42Z")

</div>

It’s weird:

```julia
# freshly started Julia
using Unitful

module M0
using Unitful
end

println(names(M0, all=true, imported=true))
println(names(Main, all=true, imported=true))

julia> 
[Symbol("#eval"), Symbol("#include"), :M0, :eval, :include]
[Symbol("##meta#58"), Symbol("#1#2"), Symbol("#3#5"), Symbol("#4#6"), :Base, :Core, :InteractiveUtils, :M0, :Main, :Revise, :Unitful, :VSCodeServer, :eval, :include]

```

For the `Main` module, `names()` returns `Unitful` , but for `M0` - not. I doubt this is intended behavior. Anybody knows whom I could ask on that point?

---

<div class="post-metadata">

### Author: ![disberd](https://avatars.discourse-cdn.com/v4/letter/d/8edcca/32.png) [@disberd](https://discourse.julialang.org/u/disberd)
#### Post date: [October 9, 2023, 11:45am UTC](https://discourse.julialang.org/t/get-all-names-accessible-from-a-module/98492/10 "2023-10-09T11:45:56Z")

</div>

@Eben60 I think you would need to follow a different approach.

From the post you linked I guess your use case is recreating the struct defined at a certain point within the module by creating a temporary submodule where you must re-import all the variables from the calling module that are used in the struct definition.

I have to do something similar to extract variables from Pluto in PlutoVSCodeDebugger.

I have a very simple function there that collect variables names that are being found in an expression only if they are defined in a targe module (in your case it will be the one where your custom macro is called from) and they are not defined neither in Main nor Base (the purpose for Base is to avoid names that are automatically re-imported from Base in every module, excluding also Main was just because in my case the generated expression is evaluated in Main, so it’s pointless to also track things already defined in Main).

Here is the function:

> <https://github.com/disberd/PlutoVSCodeDebugger.jl/blob/48cc383c8ad443686e8efc56e547a2274094ecd1/src/debugger.jl#L2-L11>

And it puts the found variable names inside a `Set` of Symbols (I use a Set so that I automatically avoid duplicates).

While it may not be already applicable as is to your use case, I think it can be a good starting point for experimenting.

EDIT:  
Here is a small example usage

```julia-repl
julia> _names = Set{Symbol}()
Set{Symbol}()

julia> module M
           a = 1
           b = 2
       end
Main.M

julia> PlutoVSCodeDebugger.extract_variables!(:(@kwdef struct Foo
               x = a
               y = b
           end); _mod = M, _names)

julia> _names
Set{Symbol} with 2 elements:
  :a
  :b

```

You could use the extracted names to specifically re-import from the calling module with an expressione like the following

```julia-repl
julia> Expr(:import, Expr(:(:), Expr(:., :., :., nameof(M)), map(x -> Expr(:., x), collect(_names))...))
:(import ..M: a, b)

```

I also do something similar to extract variable names to re-export for the `@fromparent` macro from my other package [GitHub - disberd/PlutoDevMacros.jl: Simple macros to help developing packages using Pluto.jl as base](https://github.com/disberd/PlutoDevMacros.jl) (which is also the reason why I opened this thread in the first place).  
So I had my share of headaches with macros and I might have stumbled on similar problems to what you will face 🙂

---

<div class="post-metadata">

### Author: ![Eben60](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/eben60/32/13475_2.png) [@Eben60](https://discourse.julialang.org/u/Eben60)
#### Post date: [October 10, 2023, 1:04pm UTC](https://discourse.julialang.org/t/get-all-names-accessible-from-a-module/98492/11 "2023-10-10T13:04:08Z")

</div>

@disberd, thanks a lot. So if I understand you correctly, you are suggesting to go bottom-up and collect all identifiers recursively from the expression to be processed by my macro. Yes, that can be a viable approach, I’ll try it as soon as I have some spare time. One question now: What would happen if there is a macro within that expression?

Still I think it’s worth open an issue for the `names` function - would do it later on, too. It’s annoying it doesn’t return _all_ identifiers in the given scope.
