You might be able to accomplish your actual use case with invoke, which doesn’t list methods in order but does let you accomplish something similar to what super() does in python.
A combination of which and supertype should do the trick for single argument functions. Try
function methodhierarchy(name, argtype)
methods = Vector{Method}()
push!(methods, which(name, (argtype,)))
while argtype != Any
argtype = supertype(argtype)
method = which(name, (argtype,))
if methods[end] != method
push!(methods, method)
end
end
methods
end
julia> methodhierarchy(foo, Int)
[1] foo(x::Int64) in Main at REPL[2]:1
[2] foo(x::Number) in Main at REPL[3]:1
[3] foo(x) in Main at REPL[1]:1
julia> m = methodhierarchy(foo, String)
[1] foo(x::String) in Main at REPL[4]:1
[2] foo(x) in Main at REPL[1]:1
It goes into an infinite loop with nested super calls though
And it only works when there’s one argument…
function super(cur_input)
cur_function = getfield(current_module(), stacktrace()[2].func)
println(stacktrace())
cur_type = typeof(cur_input)
cur_super_type = nothing
cur_method = which(cur_function, (cur_type,))
is_hunting_super = false
while cur_type != Any
cur_type = supertype(cur_type)
tmp_method = which(cur_function, (cur_type,))
if cur_method == tmp_method
if is_hunting_super
cur_super_type = cur_type
break
end
else
is_hunting_super = true
cur_super_type = cur_type
cur_method = tmp_method
end
end
@assert cur_super_type != nothing
cur_output = invoke(cur_function, Tuple{cur_super_type}, cur_input)
cur_output
end
function foo(x::Any)
println("Any")
end
function foo(x::Int)
println("Int")
super(x)
end
function foo(x::Number)
println("Number")
super(x)
end
function foo(x::String)
"Nu uh uh. You didn't say the magic word"
end
Can you maybe describe your problem more concrete? I think there is probably a more idiomatic way in Julia to deal with your problem. (Instead of just porting over OO ideas).
The problem with that is it won’t chain for abstract types
Int (1st call) StackFrame[super(::Int64) at In[84]:3, foo(::Int64) at In[84]:41, ...]
Number (2nd call) StackFrame[super(::Int64) at In[84]:3, foo(::Int64) at In[84]:46, super(::Int64) at In[84]:30, foo(::Int64) at In[84]:41, ...]
Number ( 3rd call -- BAD!!! ) StackFrame[super(::Int64) at In[84]:3, foo(::Int64) at In[84]:46, super(::Int64) at In[84]:30, foo(::Int64) at In[84]:46, super(::Int64) at In[84]:30, foo(::Int64) at In[84]:41, ...] Number
Notice that each of those functions were passed the concrete (::Int64) and not(::Number)
edit: for clarity, the 3rd call should have been to foo(x::Any), not to foo(x::Number).
// although, I truncated it after 3 calls, this is actually an infinite loop