Finding all the functions with a parametric abstract type as a argument

Reflective programming/Metaprogramming challenge:
I am interested in exploring which methods are defined directly for some (usually parametric) and usually abstract types. To be clear, my interest is only in those methods defined with that particular type (with a UnionAll or specific generic parameter) and not simply the list of methods with which the type could be called.

To simplify, we could only look for those that have the type in the first 2 (or whatever) arguments.

As an example, lets say I have the following types, which may be in some module

module MyModule
abstract type SomeSuper end
abstract type Pointy{T} <: SomeSuper end
struct Point{T} <: Pointy{T}
           x::T
           y::T
end

f1(x::SomeSuper) = 1
f2(x::SomeSuper) = 1
f2(x::Pointy{T}) where T = 2
f3(x::Pointy{Float64}) where T = 3
f4(x::Pointy{T}) where T = 1
end

f5(x::MyModule.Pointy{T}) where T = 1 # different namespace
f6(y, x::MyModule.Pointy{T}) where T = 1
f7(x::Point{T}) where T = 1 # note the concrete sub-type

We can call them as well, just to ensure all the names are loaded in whichever way necessayr

# calling works
p = MyModule.Point{Float64}(0.1, 0.2)
MyModule.f2(p)
MyModule.f3(p)
MyModule.f4(p)
f5(p)
f6(1, p)
f7(p)

We could even assume that they are available with using if that helps

I want to be able to have something called getfunctions which returns the list of functions that directly mention the type, or methods if that is easier. The signature would be something like

fs = getfunctions(MyModule.Pointy) # note abstract type without specific parameters

# should be
fs == [:f2, :f3, :f4, :f5, :f6] # could have namespace qualifications, if easier

In this, :f1 doesn’t match because there are no methods which mention Pointy directly, and :f7 doesn’t match because it only refers to sub-types of Pointy. All of the other ones have an argument to a method which refers to either Pointy with any parameter or a Pointy with a particular generic parameter.

Any thoughts on whether this is possible or how it could be written? I think it would be a generally useful bit of code to explore the type-system.

Not a direct answer, but with my InteractiveCodeSearch.jl you can just run @search MyModule and then type Pointy to get a rough list of functions using it.

If you want a programmatic interface, I guess you can look at what methods returns:

julia> for m in methods(MyModule.f2)
           @show m.sig
       end
m.sig = Tuple{typeof(Main.MyModule.f2),Main.MyModule.Pointy{T}} where T
m.sig = Tuple{typeof(Main.MyModule.f2),Main.MyModule.SomeSuper}
1 Like

Looks great. I want to explore rather than have a programmatic interface, so this might be perfect. My real interest is not a simple set of types, but rather examining types in Base.Number, Base.AbstractRange, etc, so I will see if the large number of values returned works in the UI.

A report: The InteractiveCodeSearch.jl based solution is pretty good. Cool package, which I hope you publicize much more! My real test, is to try to explore Base.Number, Base,AbstractFloat, etc.

The only issue is that the @search Base and then Number since it uses strings rather than types, you can get a lot of false-positives for the sort of thing I am interested in, but even in Base it was useful.

Thanks, good that you find it useful! Yeah, I guess I better make an ANN post in discourse.

I agree that string-based matching is very crude (but actually already quite useful, mostly because peco is really efficient). It would be nice to make something like hoogle where you can search functions based on signature. Now that I figured out how to search based on return type, it’s matter of coding things up…

Meanwhile, in peco you can use other search mode like regex by pressing C-r (peco.RotateFilter) a few times. It may help you decreasing false-positives (if you haven’t tried it already).

BTW, your example let me fix some bugs (thanks!). One of the bugs is that you couldn’t run @search Main :r to search all methods. Once https://github.com/JuliaLang/METADATA.jl/pull/18833 is merged, you’d be able to do that.