Search for functions whose first argument can be a specific type

In object-oriented languages, it is easy to see what methods a type has. For example, to find a replace command for strings, I just need to search in the methods that a string object exposes (using, e.g., __dict__ in python). In Julia, because of multiple dispatch, methods just occupy the global namespace, and I can’t restrict my search in the function space according to types. I was wondering if there are ways to do this.

3 Likes

have you tried methods and methodswith?

  methodswith(typ[, module or function]; supertypes::Bool=false])
  Return an array of methods with an argument of type typ.
  The optional second argument restricts the search to a particular module or function (the default is all top-level modules).
  If keyword supertypes is true, also return arguments with a parent type of typ, excluding type Any.
  methods(f, [types], [module])
  Return the method table for f.
  If types is specified, return an array of methods whose types match. If module is specified, return an array of methods defined in that module. A
  list of modules can also be specified as an array.
  │ Julia 1.4
  │
  │  At least Julia 1.4 is required for specifying a module.
7 Likes

Can you provide an example of using this to get methods for Poisson from Distributions? I tried the following, but it did not show, e.g., rand(Poisson(1)).

julia> typeof(Poisson(1))
Poisson{Float64}

julia> methods(typeof(Poisson(1)))
# 1 method for type constructor:
[1] (::Type{Poisson{T}})(λ::Real) where T<:Real in Distributions at /Users/evar/.julia/packages/Distributions/dTXqn/src/univariate/discrete/poisson.jl:26

julia> methodswith(typeof(Poisson(1)))


julia> methods(Poisson(1))
# 0 methods:

julia> methodswith(Poisson(1))
ERROR: MethodError: no method matching methodswith(::Poisson{Float64})
Closest candidates are:
  methodswith(::Type; supertypes) at /Users/julia/buildbot/worker/package_macos64/build/usr/share/julia/stdlib/v1.4/InteractiveUtils/src/InteractiveUtils.jl:168
  methodswith(::Type, ::Function) at /Users/julia/buildbot/worker/package_macos64/build/usr/share/julia/stdlib/v1.4/InteractiveUtils/src/InteractiveUtils.jl:136
  methodswith(::Type, ::Function, ::Any; supertypes) at /Users/julia/buildbot/worker/package_macos64/build/usr/share/julia/stdlib/v1.4/InteractiveUtils/src/InteractiveUtils.jl:136
  ...
Stacktrace:
 [1] top-level scope at REPL[121]:1

julia> methodswith(Poisson)
[1] ccdf(d::Poisson, x::Int64) in Distributions at /Users/evar/.julia/packages/Distributions/dTXqn/src/univariates.jl:557
[2] cdf(d::Poisson, x::Int64) in Distributions at /Users/evar/.julia/packages/Distributions/dTXqn/src/univariates.jl:556
[3] cf(d::Poisson, t::Real) in Distributions at /Users/evar/.julia/packages/Distributions/dTXqn/src/univariate/discrete/poisson.jl:113
[4] convolve(d1::Poisson, d2::Poisson) in Distributions at /Users/evar/.julia/packages/Distributions/dTXqn/src/convolution.jl:45
[5] cquantile(d::Poisson, q::Real) in Distributions at /Users/evar/.julia/packages/Distributions/dTXqn/src/univariates.jl:562
[6] entropy(d::Poisson{T}) where T<:Real in Distributions at /Users/evar/.julia/packages/Distributions/dTXqn/src/univariate/discrete/poisson.jl:68
[7] invlogccdf(d::Poisson, lq::Real) in Distributions at /Users/evar/.julia/packages/Distributions/dTXqn/src/univariates.jl:564
[8] invlogcdf(d::Poisson, lq::Real) in Distributions at /Users/evar/.julia/packages/Distributions/dTXqn/src/univariates.jl:563
[9] kurtosis(d::Poisson) in Distributions at /Users/evar/.julia/packages/Distributions/dTXqn/src/univariate/discrete/poisson.jl:65
[10] logccdf(d::Poisson, x::Int64) in Distributions at /Users/evar/.julia/packages/Distributions/dTXqn/src/univariates.jl:559
[11] logcdf(d::Poisson, x::Int64) in Distributions at /Users/evar/.julia/packages/Distributions/dTXqn/src/univariates.jl:558
[12] logpdf(d::Poisson, x::Int64) in Distributions at /Users/evar/.julia/packages/Distributions/dTXqn/src/univariates.jl:554
[13] mean(d::Poisson) in Distributions at /Users/evar/.julia/packages/Distributions/dTXqn/src/univariate/discrete/poisson.jl:52
[14] mgf(d::Poisson, t::Real) in Distributions at /Users/evar/.julia/packages/Distributions/dTXqn/src/univariate/discrete/poisson.jl:108
[15] mode(d::Poisson) in Distributions at /Users/evar/.julia/packages/Distributions/dTXqn/src/univariate/discrete/poisson.jl:54
[16] modes(d::Poisson) in Distributions at /Users/evar/.julia/packages/Distributions/dTXqn/src/univariate/discrete/poisson.jl:57
[17] params(d::Poisson) in Distributions at /Users/evar/.julia/packages/Distributions/dTXqn/src/univariate/discrete/poisson.jl:45
[18] pdf(d::Poisson, x::Int64) in Distributions at /Users/evar/.julia/packages/Distributions/dTXqn/src/univariates.jl:553
[19] quantile(d::Poisson, q::Real) in Distributions at /Users/evar/.julia/packages/Distributions/dTXqn/src/univariates.jl:561
[20] rate(d::Poisson) in Distributions at /Users/evar/.julia/packages/Distributions/dTXqn/src/univariate/discrete/poisson.jl:48
[21] sampler(d::Poisson) in Distributions at /Users/evar/.julia/packages/Distributions/dTXqn/src/univariate/discrete/poisson.jl:147
[22] skewness(d::Poisson) in Distributions at /Users/evar/.julia/packages/Distributions/dTXqn/src/univariate/discrete/poisson.jl:63
[23] var(d::Poisson) in Distributions at /Users/evar/.julia/packages/Distributions/dTXqn/src/univariate/discrete/poisson.jl:61
[24] broadcast(::typeof(pdf), d::Poisson, X::UnitRange) in Distributions at /Users/evar/.julia/packages/Distributions/dTXqn/src/univariate/discrete/poisson.jl:102
[25] broadcast!(::typeof(pdf), r::AbstractArray, d::Poisson, rgn::UnitRange) in Distributions at /Users/evar/.julia/packages/Distributions/dTXqn/src/univariate/discrete/poisson.jl:99
[26] convert(::Type{Poisson{T}}, d::Poisson{S}) where {T<:Real, S<:Real} in Distributions at /Users/evar/.julia/packages/Distributions/dTXqn/src/univariate/discrete/poisson.jl:41
[27] maximum(d::Poisson) in Distributions at /Users/evar/.julia/packages/Distributions/dTXqn/src/univariates.jl:148
[28] minimum(d::Poisson) in Distributions at /Users/evar/.julia/packages/Distributions/dTXqn/src/univariates.jl:147

julia>

You can find rand if you add the keyword argument supertypes=true:

julia> methodswith(Poisson; supertypes=true)
[snip output ...]
[96] rand(s::Sampleable) in Distributions at D:\.julia\packages\Distributions\vskB8\src\genericrand.jl:22

(Just note that Sampleable is a supertype of Poisson)

3 Likes

One more note: see that, although it is a good approximation, methodswith does not fully solve the original question (“search for functions whose first argument can be of a specific type”):

  • On the one hand, methodswith tells you about functions that have been written with methods that take specific types (or optionally their supertypes) for arguments in any position.
  • On the other hand, Any is excluded from the list of supertypes considered by methodswith (otherwise the output would be endless), but for many types there are numberless generic functions that work with them, even without the authors of the type or the function taking care of that.
  • Also, the output of methodswith is not fixed, but depends on what packages are loaded.

Anyway, Julia is not like Python: methods are not subordinate to types/classes, so I think that it is reasonable that the original question, asked from a Pythonic perspective, does not have a precise answer in Julia.

4 Likes