# Docstring for \`Method\`

**URL:** <https://discourse.julialang.org/t/docstring-for-method/92675>\
**Category:** General Usage\
**Tags:** question\
**Created:** [January 8, 2023, 3:08pm UTC](https://discourse.julialang.org/t/docstring-for-method/92675 "2023-01-08T15:08:31Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![FedeClaudi](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/fedeclaudi/32/33490_2.png) [@FedeClaudi](https://discourse.julialang.org/u/FedeClaudi)\
**Post date:** [January 8, 2023, 3:08pm UTC](https://discourse.julialang.org/t/docstring-for-method/92675/1 "2023-01-08T15:08:31Z")

</div>

Hey everyone,

I’m trying to do something that I thought would be easy but is actually rather tricky.  
I simply want to get the docstring of a `Method`.

For example:

```julia
"""
my f
"""
f(x::Int) = 2x

"""
with strings
"""
f(x::String) = print(x)

"""
and keyword args
"""
f(; y=1) = print(y)

methods

```

gives:

```julia
# 3 methods for generic function "f":
[1] f(; y) in Main at /Users/federicoclaudi/Documents/Github/Term.jl/workspace.jl:16
[2] f(x::Int64) in Main at /Users/federicoclaudi/Documents/Github/Term.jl/workspace.jl:5
[3] f(x::String) in Main at /Users/federicoclaudi/Documents/Github/Term.jl/workspace.jl:11

```

if, say, I wanted to get the docstring of the second method, what should I do?  
I know about `Docs.Binding` and `Docs.meta` to get multidocs like it’s done, for example, in the [REPL](https://github.com/JuliaLang/julia/blob/e0ba28ac29d0fe35645198a4c7f832972d1c60d5/stdlib/REPL/src/docview.jl#L164) but I was hoping there was a more direct way to get at this.  
Specifically, when the methods are constructors for a `DataType` there might be multiple methods that differ only in their keyword arguments and the approach above doesn’t distinguish them since they share the same signature.

Thank you,  
Federico

---

<div class="post-metadata">

**Author:** ![fredrikekre](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/fredrikekre/32/1688_2.png) [@fredrikekre](https://discourse.julialang.org/u/fredrikekre)\
**Post date:** [January 8, 2023, 4:23pm UTC](https://discourse.julialang.org/t/docstring-for-method/92675/2 "2023-01-08T16:23:09Z")

</div>

Is this what you are asking for?

```julia
help?> f(::String)
  with strings

julia> @doc f(::String)
  with strings

```

---

<div class="post-metadata">

**Author:** ![FedeClaudi](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/fedeclaudi/32/33490_2.png) [@FedeClaudi](https://discourse.julialang.org/u/FedeClaudi)\
**Post date:** [January 8, 2023, 6:05pm UTC](https://discourse.julialang.org/t/docstring-for-method/92675/3 "2023-01-08T18:05:50Z")

</div>

Hey thanks for getting back to me so quickly.

I’m afraid not. I need the docstring for a specific method, not for all of them. There’s way to use the signature, but it still doesn’t always cover all cases. Isn’t there a way, given an object of type `Method` to get the actual docstring that belongs to ?

---

<div class="post-metadata">

**Author:** ![jules](https://avatars.discourse-cdn.com/v4/letter/j/41988e/32.png) [@jules](https://discourse.julialang.org/u/jules)\
**Post date:** [January 8, 2023, 9:43pm UTC](https://discourse.julialang.org/t/docstring-for-method/92675/4 "2023-01-08T21:43:47Z")

</div>

> [@FedeClaudi](#):
>
> there might be multiple methods that differ only in their keyword arguments

I don’t think that’s possible, you can’t have two methods with the same type signature that only differ by keyword arguments, because the keyword arguments don’t count for dispatch.

 ![grafik](https://global.discourse-cdn.com/julialang/original/3X/f/e/fe5425d1de3ed78bc727fb75f22d441c0914e251.png)

---

<div class="post-metadata">

**Author:** ![FedeClaudi](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/fedeclaudi/32/33490_2.png) [@FedeClaudi](https://discourse.julialang.org/u/FedeClaudi)\
**Post date:** [January 8, 2023, 10:00pm UTC](https://discourse.julialang.org/t/docstring-for-method/92675/5 "2023-01-08T22:00:07Z")

</div>

That;s fair, I think you’re right.

This is the solution I landed on, it seems to get the job done, leaving it here in case folks find it useful:

```julia
using Base.Docs: meta, Binding, doc
import Markdown

"""
    get_methods_with_docstrings(obj::Union{Union, DataType, Function})

Get the docstring for each method for an object (function/datatype).
"""
function get_methods_with_docstrings(obj::Union{Union, DataType, Function})::Tuple{Vector, Vector}
    # get the parent module and the methods list for the object
    mod = parentmodule(obj)
    mm = methods(obj)

    # get the module's multidoc
    binding = Binding(mod, Symbol(obj))    
    dict = meta(mod)
    multidoc = dict[binding]
    
    # for each module, attempt to get the docstring as markdown
    docstrings = []
    for m in mm
        # cleanup signature
        sig = length(m.sig.types) == 1 ? Tuple{} : Tuple{m.sig.types[2:end]...}
        
        haskey(multidoc.docs, sig) || begin
            push!(docstrings, nothing)
        end
        docs = multidoc.docs[sig].text[1] |> Markdown.parse
        push!(docstrings, docs)
    end

    return mm, docstrings
end

```

---

<div class="post-metadata">

**Author:** ![thautwarm](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/thautwarm/32/37760_2.png) [@thautwarm](https://discourse.julialang.org/u/thautwarm)\
**Post date:** [May 17, 2024, 6:48am UTC](https://discourse.julialang.org/t/docstring-for-method/92675/6 "2024-05-17T06:48:28Z")

</div>

> [@FedeClaudi](#):
>
> ```julia
> using Base.Docs: meta, Binding, doc
> import Markdown
> 
> """
> get_methods_with_docstrings(obj::Union{Union, DataType, Function})
> 
> Get the docstring for each method for an object (function/datatype).
> """
> function get_methods_with_docstrings(obj::Union{Union, DataType, Function})::Tuple{Vector, Vector}
> # get the parent module and the methods list for the object
> mod = parentmodule(obj)
> mm = methods(obj)
> 
> # get the module's multidoc
> binding = Binding(mod, Symbol(obj))    
> dict = meta(mod)
> multidoc = dict[binding]
>     
> # for each module, attempt to get the docstring as markdown
> docstrings = []
> for m in mm
> # cleanup signature
> sig = length(m.sig.types) == 1 ? Tuple{} : Tuple{m.sig.types[2:end]...}
>         
> haskey(multidoc.docs, sig) || begin
> push!(docstrings, nothing)
> end
> docs = multidoc.docs[sig].text[1] |> Markdown.parse
> push!(docstrings, docs)
> end
> 
> return mm, docstrings
> end
> 
> ```

This is quite a useful snippet, but for relatively complex cases, e.g., `Core.TypeVar` would appear in `sig` (DataType).

A real-world case did happen to me where the above code didn’t work due to inconsistent handling of DataType with “non-normalized” `Core.TypeVar`s:

```julia
julia> Tuple{Union{Number, AbstractVecOrMat{<:Number}}}.parameters[1].b
AbstractVecOrMat{<:Number} (alias for Union{AbstractArray{var"#s6", 1}, AbstractArray{var"#s6", 2}} where var"#s6"<:Number)

julia> t.parameters[1].b
AbstractVecOrMat{<:Number} (alias for Union{AbstractArray{var"#s10", 1}, AbstractArray{var"#s10", 2}} where var"#s10"<:Number)

```

It seems that using `string`s to lookup the type might satisfy more common cases, and this is a revised version:

```julia
using Base.Docs: meta, Binding, doc
import Markdown

"""
    get_methods_with_docstrings(obj::Union{Union, DataType, Function})

Get the docstring for each method for an object (function/datatype).
"""
function get_methods_with_docstrings(obj::Union{Union, DataType, Function})
    # get the parent module and the methods list for the object
    mod = parentmodule(obj)
    mm = methods(obj)

    # get the module's multidoc
    binding = Binding(mod, Symbol(obj))    
    dict = meta(mod)
    multidoc = Dict{String, Any}(string(k) => v for (k, v) in dict[binding].docs)
    
    # for each module, attempt to get the docstring as markdown
    docstrings = Any[]
    for m in mm
        # cleanup signature
        sig = length(m.sig.types) == 1 ? Tuple{} : Tuple{m.sig.types[2:end]...}
        sig_as_str = string(sig)

        haskey(multidoc, sig_as_str) || continue

        docs = multidoc[sig_as_str].text[1] |> Markdown.parse
        push!(docstrings, m => docs)
    end

    return docstrings
end

```

Besides, I guess there are some internal utility do the process of transforming `m.sig` to a stable `sig` used in `multidoc`, which shall be a complete solution, but I cannot find such transformation in `Base` or `Core`.
