Obtaining parameter types for a function

Hello all,

Is there any way to obtain the parameter types for a given method? For example, if I have function f(x::Int64) x end, is there a way to recover the type of parameter x? I realize that generic methods may make this complex or impossible but I thought I’d ask.

Thanks!

Just getting the obvious out of the way:

julia> function f(x::Int)
           @show typeof(x)
           return x
       end;

julia> f(1);
typeof(x) = Int64

I assume this is not what you want?

2 Likes

Yes, sorry, I should have been clearer. What I imagine is more like:

julia> parameter_types(f);
x::Int64

That’s not a well posed idea in Julia because functions can have as many heterogeneous methods as you like.

julia> f(x::Int) = x + 1
f (generic function with 1 method)

julia> f(s::String) = length(s)
f (generic function with 2 methods)

julia> f(v::Vector) = v'v
f (generic function with 3 methods)

julia> f(1), f("hi"), f([1,2,3])
(2, 2, 14)

Only methods have ‘parameters’, though we prefer the term signature here.

julia> methods(f)
# 3 methods for generic function "f":
[1] f(x::Int64) in Main at REPL[5]:1
[2] f(s::String) in Main at REPL[6]:1
[3] f(v::Vector{T} where T) in Main at REPL[7]:1

Methods themselves aren’t really first-class objects in julia though, so there’s no blessed api to ask a specific method what it’s signature is.

Depending on your usecase however, one thing you could use is hasmethod, e.g.

julia> hasmethod(f, (Int,))
true

julia> hasmethod(f, (Int, Int))
false

julia> hasmethod(f, (String, ))
true
4 Likes

Probably not official syntax, but you can do the following:

julia> f(x::Int) = x
       f(x::Float64) = x;

julia> methods(f).ms[1].sig
Tuple{typeof(f), Int64}

julia> methods(f).ms[2].sig
Tuple{typeof(f), Float64}
2 Likes

Thanks - so methods(f).ms[2].sig (for example) is actually returning a type. Is there any way to then index this type so as to get the second element?

Thank you - iterating through a list of potential input types like this may be the best way to go.

1 Like

That’s the best I could come up with:

julia> second_type(::Type{Tuple{F,T}}) where {F,T} = T
second_type (generic function with 3 methods)

julia> second_type(methods(f).ms[1].sig)
Int64

It’s not getting any prettier… :frowning_face:

1 Like

For the sub-problem of getting a particular element in Tuple{...}:

julia> fieldtypes(Tuple{Int, String})
(Int64, String)

julia> fieldtypes(Tuple{Int, String})[2]
String
3 Likes

Haha. But all useful things have their beauty.

Right, thanks. That’s perfect then. Thanks all, it’s been educational.

I’m curious. What’s this useful for?

1 Like

My original question? It’s a bit niche but I have a situation where the package user can pass a function. To make this as ergonomic as possible for the user, I’d like to write it such that the function will take either one of the JSON types (array, string, object/dict etc), or a struct that the JSON is expected to parse to, as its only argument. The JSON can then be parsed in advance into the appropriate type. But obviously this requires me to be able to find the function’s parameter type.

1 Like

Does this work?

methods(f)[1].sig.parameters[2]