# Query regarding namespaces when adding a method using a macro

**URL:** <https://discourse.julialang.org/t/query-regarding-namespaces-when-adding-a-method-using-a-macro/115392>\
**Category:** General Usage\
**Tags:** macros, function\
**Created:** [June 9, 2024, 1:29pm UTC](https://discourse.julialang.org/t/query-regarding-namespaces-when-adding-a-method-using-a-macro/115392 "2024-06-09T13:29:28Z")\
**Posts on this page:** 5\
**Page:** 1

<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 9, 2024, 1:29pm UTC](https://discourse.julialang.org/t/query-regarding-namespaces-when-adding-a-method-using-a-macro/115392/1 "2024-06-09T13:29:28Z")

</div>

I am confused about how namespaces are being applied in the following code, and would appreciate some help.

```julia
module A

using LinearAlgebra

abstract type AbsType end

struct SubType <: AbsType end

macro newmethod()
	quote
		function A.Diagonal(S::A.SubType) end
	end
end

@newmethod

function Diagonal(S::AbsType) end # this should be a different function

end

```

What I expect: the `Diagonal` defined in the module `A` should be different from the one in `LinearAlgebra`, as the function was neither explicitly imported nor was the method defined by specifying the namespace.

What I find:

```julia
julia> methods(A.Diagonal)
# 9 methods for type constructor:
 [1] LinearAlgebra.Diagonal(S::Main.A.SubType)
     @ Main.A REPL[1]:11
 [2] LinearAlgebra.Diagonal(A::LinearAlgebra.Bidiagonal)
     @ ~/.julia/juliaup/julia-1.10.4+0.x64.linux.gnu/share/julia/stdlib/v1.10/LinearAlgebra/src/special.jl:14
 [3] LinearAlgebra.Diagonal(A::LinearAlgebra.SymTridiagonal)
     @ ~/.julia/juliaup/julia-1.10.4+0.x64.linux.gnu/share/julia/stdlib/v1.10/LinearAlgebra/src/special.jl:23
 [4] LinearAlgebra.Diagonal(s::LinearAlgebra.UniformScaling, m::Integer)
     @ ~/.julia/juliaup/julia-1.10.4+0.x64.linux.gnu/share/julia/stdlib/v1.10/LinearAlgebra/src/special.jl:271
 [5] LinearAlgebra.Diagonal(D::LinearAlgebra.Diagonal)
     @ ~/.julia/juliaup/julia-1.10.4+0.x64.linux.gnu/share/julia/stdlib/v1.10/LinearAlgebra/src/diagonal.jl:105
 [6] LinearAlgebra.Diagonal(v::AbstractVector{T}) where T
     @ ~/.julia/juliaup/julia-1.10.4+0.x64.linux.gnu/share/julia/stdlib/v1.10/LinearAlgebra/src/diagonal.jl:14
 [7] LinearAlgebra.Diagonal(A::LinearAlgebra.Tridiagonal)
     @ ~/.julia/juliaup/julia-1.10.4+0.x64.linux.gnu/share/julia/stdlib/v1.10/LinearAlgebra/src/special.jl:34
 [8] LinearAlgebra.Diagonal(A::AbstractMatrix)
     @ ~/.julia/juliaup/julia-1.10.4+0.x64.linux.gnu/share/julia/stdlib/v1.10/LinearAlgebra/src/diagonal.jl:98
 [9] LinearAlgebra.Diagonal(S::Main.A.AbsType)
     @ Main.A REPL[1]:17

```

Why is there a method `LinearAlgebra.Diagonal(S::Main.A.AbsType)`? I didn’t ask for this.

This only happens if the method definition `Diagonal(S::AbsType)` comes after the macro call `@newmethod`, and this seems to add a new method to `LinearAlgebra.Diagonal` instead of to `A.Diagonal`.

---

<div class="post-metadata">

**Author:** ![sgaure](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/sgaure/32/14779_2.png) [@sgaure](https://discourse.julialang.org/u/sgaure)\
**Post date:** [June 9, 2024, 2:48pm UTC](https://discourse.julialang.org/t/query-regarding-namespaces-when-adding-a-method-using-a-macro/115392/2 "2024-06-09T14:48:46Z")

</div>

I’m not sure what actually happens here, but it seems the module qualification `A.` in the macro somehow serves to override the explicit import requirement. Perhaps because `LinearAlgebra.Diagonal` is available in the `A` module, and the definition is qualified with a module name?

Anyway, depending on what you want to achieve, you should perhaps escape the function name:

```julia
macro newmethod()
	quote
		function esc(Diagonal)(S::A.SubType) end
	end
end

```

or the entire quote:

```julia
macro newmethod()
	quote
		function Diagonal(S::A.SubType) end
	end |> esc
end

```

to avoid macro hygiene renaming it to something like `#1#Diagonal`.

---

<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 9, 2024, 7:02pm UTC](https://discourse.julialang.org/t/query-regarding-namespaces-when-adding-a-method-using-a-macro/115392/3 "2024-06-09T19:02:12Z")

</div>

I’m actually trying to debug a scenario where this worked accidentally when it shouldn’t have, so I’m not really looking for a workaround. In my use case, the last function should have been defined as

```julia
function LinearAlgebra.Diagonal(S::AbsType) end

```

but, perplexingly, this worked without the qualification, which seems like a bug?

I do want all the `Diagonal`s to refer to the `LinearAlgebra` one, especially the one inside the macro. Moreover, the macro is intended to be used downstream, and I don’t want to assume that `LinearAlgebra` is loaded at the macro call site. So, ideally, I want to use `A.Diagonal` to refer to `LinearAlgebra.Diagonal` within the macro, which is guaranteed to be defined.

The first suggestion above doesn’t appear to work:

```julia
julia> module A

       using LinearAlgebra

       abstract type AbsType end

       struct SubType <: AbsType end

       macro newmethod()
               quote
                       function esc(Diagonal)(S::A.SubType) end
               end
       end

       @newmethod

       function Diagonal(S::AbsType) end

       end
WARNING: replacing module A.
ERROR: syntax: invalid function name "#90#esc(A.Diagonal)" around REPL[1]:11
Stacktrace:
 [1] top-level scope
   @ REPL[1]:15

```

Perhaps I’m misunderstanding how this is meant to be used.

The second solution does answer the original question, as it correctly defines `Diagonal` within `A`.

It would still be good to understand what’s happening in the original case, though.

---

<div class="post-metadata">

**Author:** ![sgaure](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/sgaure/32/14779_2.png) [@sgaure](https://discourse.julialang.org/u/sgaure)\
**Post date:** [June 10, 2024, 6:32am UTC](https://discourse.julialang.org/t/query-regarding-namespaces-when-adding-a-method-using-a-macro/115392/4 "2024-06-10T06:32:47Z")

</div>

I agree that the second method definition works because of an apparent bug, or an undocumented feature.

Anyway, you should just define the macro as:

```julia
macro newmethod()                                                                            
    quote                                                                                    
        function LinearAlgebra.Diagonal(S::A.SubType) end                                    
    end                                                                                      
end                                                                                          

```

It will expand to something that works, and it’s clearer what’s intended.

```julia
julia> @macroexpand A.@newmethod
quote
    #= REPL[13]:9 =#
    function (Main.A.LinearAlgebra).Diagonal(var"#26#S"::(Main.A.A).SubType)
        #= REPL[13]:9 =#
        #= REPL[13]:9 =#
    end
end

```

---

<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 10, 2024, 2:07pm UTC](https://discourse.julialang.org/t/query-regarding-namespaces-when-adding-a-method-using-a-macro/115392/5 "2024-06-10T14:07:24Z")

</div>

The behavior above seems to be a bug, where methods may be added to a constructor without it being imported:

> <https://github.com/JuliaLang/julia/issues/25744>
>
> Not sure if this is intended:
> 
> \`\`\`jl
> julia\> UUID
> ERROR: UndefVarError: UUID …not defined
> 
> julia\> using Random: UUID
> 
> julia\> UUID(x::String) = UUID(rand(UInt128)) # OK?
> UUID
> 
> julia\> UUID("foo")
> 8c68d00a-33d1-777d-c4a1-0a41759d1581
> 
> julia\> using Base: getindex
> 
> julia\> struct Foo end
> 
> julia\> getindex(::Foo) = print("Hello")
> ERROR: error in method definition: function Base.getindex must be explicitly imported to be extended
> \`\`\`
