How do you get super() functionality in Julia?

For example, let’s say you have

foo(x::Any) = 1
foo(x::Int) = 2
foo(x::Number) = 3
foo(x::String) = "Nu uh uh. You didn't say the magic word"

so that foo is a generic function with 4 methods


Let’s say I have x = 10.

How would I get a list of all the foo functions applicable to x = 10 in order of specificity?

// i.e. the first three functions from above


edit: the use case is I want to have some functions that bubble up.

Or in other words, add a concept of the super function

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.

2 Likes

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
3 Likes

This is what I’m currently working with.

It goes into an infinite loop with nested super calls though :frowning:

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).

1 Like

Yeah, a better description of the problem and the goal to achieve would be a good start.

Parsing the stacktrace text output is smelly anyways :wink:

This comes up in web frameworks when you care about how information is sent up and down trees.

It just boils down to being able to call the next least specific function.

Julia-0.6.4> x = 1
1

Julia-0.6.4> foo(x)
2

Julia-0.6.4> invoke(foo, Tuple{supertype(typeof(x))}, x)
3
1 Like

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

That is impossible to do with a function. It doesn’t have any access to the context.

2 Likes

And just to be clear. It’s not possible with a callsite local macro either.

1 Like