How to reach a function definition

I was just going through the github repo of Plots.jl and in it I was trying to find the function definition KW (Line number 52: https://github.com/JuliaPlots/Plots.jl/blob/1ceb3a561f5e9f20471636865180d603d09753ed/src/plot.jl)

It gives me bonkers that everytime I need to search for the whole repo to find the source of the function. It gives me pain in searching through all files.

How do you guys overcome from this ?

1 Like

Do you know @edit and @less? Here KW is actually a type, not a function:

julia> using Plots; typeof(KW)
DataType

julia> KW
Dict{Symbol, Any}

But you can still use @less KW() or @less KW(:a=>1) to find the constructor definitions.

I don’t think there’s an easy way to find where KW is defined as an alias for Dict{Symbol, Any}. For this I actually check out the repo and use grep.

Related issue: https://github.com/JuliaLang/julia/issues/14356

3 Likes

Do you know that you can search using the Github search bar, correct?

However, most of the cases the solutions @sijo gave are sufficient.

2 Likes

Thanks @sijo for the reply.

I have found other cases like this in Gadfly repo: Gadfly.jl/Gadfly.jl at 26742d96266ad508cf8108a7b3fc1f3a61e3bb95 · GiovineItalia/Gadfly.jl · GitHub

In line number 24 spy function is getting exported, but the problem is how can I find the definition or I can’t even say from which file that function belongs too.

After searching the github repo through search bar by typing spy and filtering out of list of files then I was able to find it’s existence in Gadfly.jl/poetry.jl at ac1980797b9ae411e17917156e78c5a9b64b33c9 · GiovineItalia/Gadfly.jl · GitHub

Do you have any technique to find the source of the definition. I’m from a python background and it’s becoming difficult for me to traverse through source codes of popular julia packages and it’s hitting me hard when I try to find from where the functions are originating.

You can give the search at JuliaHub a go. If the package is loaded, then @edit/@less/@which are probably most useful. An IDE like Juno or VSCode also allows you to Ctrl-Click the symbol to go to its definition.

6 Likes

Thanks alot @pfitzseb

If you have a working call for the function, you can use @less or @edit to see the source code. For example spy must be called with a matrix, so you can do @less spy([1 2; 3 4]).

If you just want to see the file and line number (not the source), you can use @which:

julia> @which spy([1 2; 3 4])
spy(M::AbstractMatrix{T} where T, elements::Union{Function, Gadfly.Element, Theme, Type}...; mapping...) in Gadfly at /home/j/.julia/packages/Gadfly/nN3lf/src/poetry.jl:135

(You can also use @which spy to see in which module the function is defined.)

In the two cases above, you must write a complete function call with parameters. This way, Julia can find the definition of the method you want (which depends on the type of the parameters).

If you don’t know how to call spy, or if you want to find the definitions of all methods (for all types of parameters), use methods:

julia> methods(spy)
# 1 method for generic function "spy":
[1] spy(M::AbstractMatrix{T} where T, elements::Union{Function, Gadfly.Element, Theme, Type}...; mapping...) in Gadfly at /home/j/.julia/packages/Gadfly/nN3lf/src/poetry.jl:135

Here there is only one method, but for the example the filter function has many methods:

julia> methods(filter)
# 12 methods for generic function "filter":
[1] filter(f, t::Tuple{Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Vararg{Any, N}} where N) in Base at tuple.jl:345
[2] filter(f, xs::Tuple) in Base at tuple.jl:342
[3] filter(f, a::Array{T, N}) where {T, N} in Base at array.jl:2502
[4] filter(f, d::AbstractDict) in Base at abstractdict.jl:429
[5] filter(f, Bs::BitArray) in Base at bitarray.jl:1748
[6] filter(f, a::AbstractArray) in Base at array.jl:2514
[7] filter(pred, s::AbstractSet) in Base at abstractset.jl:414
[8] filter(f, s::Union{SubString{String}, String}) in Base at strings/substring.jl:242
[9] filter(f, s::AbstractString) in Base at strings/basic.jl:622
[10] filter(f, itr::Base.SkipMissing{var"#s832"} where var"#s832"<:AbstractArray) in Base at missing.jl:381
[11] filter(f::Function, l::DataStructures.MutableLinkedList{T}) where T in DataStructures at /home/j/.julia/packages/DataStructures/ixwFs/src/mutable_list.jl:92
[12] filter(f::Function, l::DataStructures.LinkedList{T}) where T in DataStructures at /home/j/.julia/packages/DataStructures/ixwFs/src/list.jl:81

And the package DataFrames.jl for example defines many more methods for filter, so if I execute using DataFrames; methods(filter) I see yet more results:

julia> using DataFrames

julia> methods(filter)
# 23 methods for generic function "filter":
[1] filter(f, t::Tuple{Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Vararg{Any, N}} where N) in Base at tuple.jl:345
[2] filter(f, xs::Tuple) in Base at tuple.jl:342
[3] filter(f, a::Array{T, N}) where {T, N} in Base at array.jl:2502
[4] filter(f, d::AbstractDict) in Base at abstractdict.jl:429
[5] filter(f, Bs::BitArray) in Base at bitarray.jl:1748
[6] filter(f, a::AbstractArray) in Base at array.jl:2514
[7] filter(pred, s::AbstractSet) in Base at abstractset.jl:414
[8] filter(f, s::Union{SubString{String}, String}) in Base at strings/substring.jl:242
[9] filter(f, s::AbstractString) in Base at strings/basic.jl:622
[10] filter(f, itr::Base.SkipMissing{var"#s832"} where var"#s832"<:AbstractArray) in Base at missing.jl:381
[11] filter(f::Function, l::DataStructures.MutableLinkedList{T}) where T in DataStructures at /home/j/.julia/packages/DataStructures/ixwFs/src/mutable_list.jl:92
[12] filter(f::Function, l::DataStructures.LinkedList{T}) where T in DataStructures at /home/j/.julia/packages/DataStructures/ixwFs/src/list.jl:81
[13] filter(::Pair{var"#s266", B} where {var"#s266"<:AsTable, B}, gdf::GroupedDataFrame) in DataFrames at /home/j/.julia/packages/DataFrames/zXEKU/src/groupeddataframe/groupeddataframe.jl:928
[14] filter(::Pair{var"#s266", B} where {var"#s266"<:AbstractVector{Int64}, B}, gdf::GroupedDataFrame) in DataFrames at /home/j/.julia/packages/DataFrames/zXEKU/src/groupeddataframe/groupeddataframe.jl:911
[15] filter(::Pair{var"#s266", B} where {var"#s266"<:(AbstractVector{var"#s164"} where var"#s164"<:AbstractString), B}, gdf::GroupedDataFrame) in DataFrames at /home/j/.julia/packages/DataFrames/zXEKU/src/groupeddataframe/groupeddataframe.jl:907
[16] filter(::Pair{var"#s266", B} where {var"#s266"<:AbstractVector{Symbol}, B}, gdf::GroupedDataFrame) in DataFrames at /home/j/.julia/packages/DataFrames/zXEKU/src/groupeddataframe/groupeddataframe.jl:905
[17] filter(::Pair{var"#s266", B} where {var"#s266"<:Union{AbstractString, Signed, Symbol, Unsigned}, B}, gdf::GroupedDataFrame) in DataFrames at /home/j/.julia/packages/DataFrames/zXEKU/src/groupeddataframe/groupeddataframe.jl:903
[18] filter(::Pair, gdf::GroupedDataFrame) in DataFrames at /home/j/.julia/packages/DataFrames/zXEKU/src/groupeddataframe/groupeddataframe.jl:909
[19] filter(f, gdf::GroupedDataFrame) in DataFrames at /home/j/.julia/packages/DataFrames/zXEKU/src/groupeddataframe/groupeddataframe.jl:901
[20] filter(::Pair{var"#s23", B} where {var"#s23"<:AsTable, B}, df::AbstractDataFrame; view) in DataFrames at /home/j/.julia/packages/DataFrames/zXEKU/src/abstractdataframe/abstractdataframe.jl:1026
[21] filter(::Pair{var"#s20", B} where {var"#s20"<:Union{AbstractVector{var"#s19"} where var"#s19"<:Integer, AbstractVector{var"#s18"} where var"#s18"<:AbstractString, AbstractVector{var"#s17"} where var"#s17"<:Symbol}, B}, df::AbstractDataFrame; view) in DataFrames at /home/j/.julia/packages/DataFrames/zXEKU/src/abstractdataframe/abstractdataframe.jl:1012
[22] filter(::Pair, df::AbstractDataFrame; view) in DataFrames at /home/j/.julia/packages/DataFrames/zXEKU/src/abstractdataframe/abstractdataframe.jl:1001
[23] filter(f, df::AbstractDataFrame; view) in DataFrames at /home/j/.julia/packages/DataFrames/zXEKU/src/abstractdataframe/abstractdataframe.jl:996
2 Likes

Thanks for the elaborate explanation for local projects. I’ll consider these for local search.