Yes, it is possible. But from what I can see this is not supported yet.
However, you can use the following function to achieve the desired functionality:
function fancymethods(x)
tsyg = Tuple{x,Vararg{Any}}
temp = Base._methods_by_ftype(tsyg, -1, Base.get_world_counter())
ms = Method[]
for m in temp::Vector
m = m::Core.MethodMatch
push!(ms, m.method)
end
Base.MethodList(ms, x.name.mt)
end
It required a little digging, and I donāt have much time to explain everything right now (if a detailed explanation is needed, I can provide it later).
This is not defined under Base
and I didnāt test it with types defined under various modules - so I cannot provide many guarantees at this point. Iāll make it more robust later.
The usage differs from parametric struct vs non-parametric.
Examples:
struct A{T}
x::T
end
(a::A)(y) = a.x + y
(b::A)(x::String) = string(b.x) * x
(c::A{Float64})(x::Float64) = c.x + x
fancymethods(A{Any})
The above fancymethods
call will produce:
# 2 methods for callable object:
[1] (b::A)(x::String)
@ Main ~/code/teach.jl/cobj.jl:5
[2] (a::A)(y)
@ Main ~/code/teach.jl/cobj.jl:4
You can see that the A{Float64}
was ignored.
However, calling fancymethods(A{Float64})
will produce, as expected:
# 3 methods for callable object:
[1] (b::A)(x::String)
@ Main ~/code/teach.jl/cobj.jl:5
[2] (c::A{Float64})(x::Float64)
@ Main ~/code/teach.jl/cobj.jl:6
[3] (a::A)(y)
@ Main ~/code/teach.jl/cobj.jl:4
The idea is that you donāt need to use an instance element; the type will suffice. But you need to be careful since A{TypeA}
is not necessarily the same as A{TypeB}
(e.g., the returned methods follow the dispatch rules).
For non-parametric types, things are straightforward:
struct B
x::Int
end
(b::B)(x::String) = string(b.x) * x
(b::B)(y) = b.x + y
fancymethods(B)
Will produce:
# 2 methods for callable object:
[1] (b::B)(x::String)
@ Main ~/code/teach.jl/cobj.jl:20
[2] (b::B)(y)
@ Main ~/code/teach.jl/cobj.jl:22
The fancymethods
function I wrote above is specially designated to get the callable object methods from using the type instead of the instance (if no method is defined for the object, youāll get an empty MethodList
).
Rely on the standard methods
for everything else.
Have fun.
P. S. I think this would be helpful to be part of Base
(the API should be something like methods(T, withobjectmethods=true)
- this would return both the constructors for T and the callable object methods - or maybe the keyword can be used to indicate that only the callable object-related methods should be returned).