Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Default argument value in function documentation #107

Open
ShuhuaGao opened this issue Feb 5, 2021 · 11 comments · May be fixed by #170
Open

Default argument value in function documentation #107

ShuhuaGao opened this issue Feb 5, 2021 · 11 comments · May be fixed by #170

Comments

@ShuhuaGao
Copy link

Consider the following documentation for a function f1 in a module CGP

"""
$(TYPEDSIGNATURES)
"""
function f1(a::Int, b::Int=0)
    return a + b
end

The generated documentation is
Snipaste_2021-02-05_14-53-00

Two signatures are produced, but information of the default value is lost. I have to document the default value of b manually.

Is it possible to produce a single signature that contains the default value? Something like follows

f1(a::Int64, b::Int64=0) -> Int64
@MichaelHatherly
Copy link
Member

I recall trying to add this a long time ago, works well for the small cases such as numbers and the like, but as soon as you have a default value being some kind of complex nested object the info becomes more of a hindrance than a help. Would need some kind of display limiting if we tried this again.

@ShuhuaGao
Copy link
Author

ShuhuaGao commented Feb 5, 2021

Would need some kind of display limiting if we tried this again.

It makes sense since most default values tend to be constants of some primitive types, e.g., numbers and string. For other more complicated cases, a placeholder may be used, like #i for the i-th default value. The author is required to document these placeholders manually.

f(a::Int64, b::ComplexType=#1, c::ComplexType=#2)

The same issue exists in keyword arguments. Consider the following function

"""
$(TYPEDSIGNATURES)
"""
function f_default(a::Int=1, b::Int=2; c::String="Hello", d::Float64=3.14)
end

which generates
Snipaste_2021-02-05_16-42-02
Also, it is not obvious to see from the above signatures whether the signature f_default(a::Int64; c) is legal. Of course, listing all possible methods may encounter the combinational explosion problem. Thus, showing default values of selected types or a placeholder otherwise may be a solution.

@andyDoucette
Copy link

+1 on this. Having the defaults in the signatures is very important. I think 98% of the time, the defaults are simple things like integers, short strings, bools, etc. Converting the default to a string and having a maximum length with a "..." at the end if it exceeds that should cover the vast majority of the cases, I'd think. I'd do it myself but I have no idea how to even get the default. :) Cudos to making this package.

@MichaelHatherly
Copy link
Member

It's possible to retrieve default argument values, it's just probably going to require digging into the output of code_lowered since the documented Expr itself is never saved. You'd want to start by looking at how the current TYPEDSIGNATURES does it's thing and then use a code_lowered to access the IR and extract values from there. This is unlikely to be a particularly easy thing to do robustly.

@JanWeidnerPTW
Copy link

since the documented Expr itself is never saved.

Is there some technical obstacle with saving the documented expression? The expression seems to be very valuable information.

@MichaelHatherly
Copy link
Member

#133 is intended to add support for this kind of thing. I just need some spare time to actually finish it off though.

@JanWeidnerPTW
Copy link

Awesome! BTW let me take this opportunity to thank you for all the great work you did on the julia documentation system @MichaelHatherly

@MichaelHatherly
Copy link
Member

Thanks @JanWeidnerPTW!

@MichaelHatherly
Copy link
Member

I'll probably merge #133 sometime thing week, after which it's just a matter of using the feature to implement a fix for this one.

@JamesWrigley
Copy link

Could you elaborate a bit on that? It's not clear to me how to get the expression into an Abbreviation.

@MichaelHatherly
Copy link
Member

Could you elaborate a bit on that? It's not clear to me how to get the expression into an Abbreviation.

Define an interpolation method that takes an Abbreviation object and adds the interpolation second argument (which is the expression that is being documented) to a new instance of the Abbreviation object and returns that. E.g.

julia> using DocStringExtensions

julia> struct CapturedExpr <: DocStringExtensions.Abbreviation
           expr::Union{Nothing,Expr}
       end

julia> DocStringExtensions.interpolation(ce::CapturedExpr, ex) = CapturedExpr(ex)

julia> const CAPTURED_EXPR = CapturedExpr(nothing)
CapturedExpr(nothing)

julia> function DocStringExtensions.format(ce::CapturedExpr, buf, doc)
           println(buf, "```")
           Meta.show_sexpr(buf, ce.expr)
           println(buf, "\n```")
       end

julia> """
       This is the captured expression:
       
       $(CAPTURED_EXPR)
       """
       f(x) = x + 1
f

help?> f
search: f fd for fma fld fld1 fill fdio frexp foldr foldl flush floor float first fill! fetch fldmod filter falses finally foreach fldmod1 findmin findmax findall

  This is the captured expression:

  (:(=), (:call, :f, :x), (:block,
      :(#= REPL[7]:6 =#),
      (:call, :+, :x, 1)
    ))

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants