Get module of a caller

module A
   foo(???) = println("I've been called from $???")
end

module B
    import A
    A.foo()   # should pring "I've been called from B"
end

Is it possible to get this behavior, i.e. find out the caller’s module without requiring it to explicitly pass @__MODULE__? I tired:

foo(; mod=@__MODULE__)

But for obvious reasons it returns the module of foo itself instead of the caller.

julia> module A                       
       function foo()                 
           s = stacktrace()           
           get(s[2].linfo).def.module 
       end                            
       end                            
A                                     
                                      
julia> module B                       
       using A                        
       foo() = A.foo()                
       end                            
B                                     
                                      
julia> B.foo()                        
B                                                                      

Obviously needs error handling, probably only works on 0.6, doesn’t quite do what you want (since it needs to be called in a function defined in B) and is generally bad since it reaches into internals, but that is at least one way to get what you want :slight_smile:

3 Likes

Interesting solution, thanks!

For reference, here’s Julia 0.7 version:

module A                       
function foo()                 
    s = stacktrace()           
    s[2].linfo.def.module 
end                            
end                            

module B                       
using Main.A                        

foo() = A.foo()                

end                            

B.foo()  # ==> Main.B

1 Like

This does not seem to work for macros, does somebody know how to access this from a macro?

module A                       
macro foo()                 
    s = stacktrace()           
    s[end].linfo.def.module 
end                            
end                            

module B                       
using Main.A                        

foo() = A.@foo()                

end                            

B.foo()  # WRONG: ==> Main.A

it returns Main.A instead of Main.B, is that a bug?

No, that’s just a consequence of the differences between macros and functions. You want

julia> module A                       
       macro foo()                 
           __module__
       end                            
       end
Main.A

julia> module B                       
       using Main.A                        

       foo() = A.@foo()                

       end
Main.B

julia> B.foo()
Main.B

instead. See here for why that works.

2 Likes