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

Include the defaults for keyword arguments #19

Open
pwl opened this issue Aug 22, 2016 · 6 comments
Open

Include the defaults for keyword arguments #19

pwl opened this issue Aug 22, 2016 · 6 comments

Comments

@pwl
Copy link

pwl commented Aug 22, 2016

For example, DocStringExtensions produces the signature

iterate(ivp; solver, opts...)

for the following function definition

function iterate{S<:AbstractSolver}(ivp::IVP;
                                    solver::Type{S} = RKIntegratorAdaptive{:rk45},
                                    opts...)

In some cases this might be enough, but it would be helpful to be able to generate an output including the default value for the keyword arguments like this

iterate(ivp; solver=RKIntegratorAdaptive{:rk45}, opts...)

Possibly with a switch to turn this behavior on or off.

@MichaelHatherly
Copy link
Member

Some initial prototypes of this package did include the default values for keywords, but I chose to drop them from the initial release since it quite quickly results in signatures that aren't all that readable I think.

Some things that can be done to make it a little more readable:

  • A switch, as you've suggested. Would this be a per-docstring or per-module switch?
  • Split long signatures over multiple lines.

Another problem I encountered was that some default values are just too big to easily fit into the signature, such as something like:

const DEFAULT = collect(1:100)
func(; keyword = DEFAULT) = # ...

Of course, that's quite a contrived example, and perhaps it wouldn't be much of a problem in the wild, but worth keeping in mind. Note that we don't have access to the expression representing the signature, only the actual Function object, so it's not possible to just print out keyword = DEFAULT I believe.

One option that could work quite nicely is to have a separate Abbreviation, perhaps called KEYWORDS, that generates a list of keywords and their values. This would be separate from the SIGNATURES abbreviation. It would look something like:

"""
$(SIGNATURES)

# Keywords

$(KEYWORDS)

...
"""
func(; foo = 1, bar = 2, baz = 3) = # ...

and would generate something like

```julia
func(; foo, bar, baz)
```

# Keywords

  * `foo = 1`
  * `bar = 2`
  * `baz = 3`

...

My view is that trying to fit too much information into a single abbreviation probably won't be too helpful to readers of the docs, though if it can be done elegantly then I'd be happy to be proved wrong.

@pwl
Copy link
Author

pwl commented Aug 22, 2016

The switch would have to be per docstring. The lengthy defaults would be trimmed or omitted completely. But then, how do you decide which values are lengthy and how do you trim them? Where do you insert the line breaks? Wouldn't KEYWORDS have to deal with the lengthy defaults too?

But all this concerned, would it be possible to have a switch that would just plug in the defaults and another switch to force line breaks between arguments, so that the user can opt in on both behaviors? Then let the user decide if the output is too long or unreadable. Is it even technically possible to have per docstring switches like that?

Alternatively there could be global formatting options (do we insert line breaks? do we trim the defaults? do we print the defaults by default?) and a statement $(SIGNATURES_WITH_DEFAULTS) including the defaults in the signature. I don't know how readable the output be but I would gladly try it out. Sorry if this might sound unrealistic, I've got no idea how the current functionality is implemented and what's possible or not.

it's not possible to just print out keyword = DEFAULT

That's a pity, I was going to suggest that. I naively thought that this package works on strings representing the definitions, not the Function objects themselves.

By the way, why is SIGNATURES plural? In which case does it print more then one signature?

@MichaelHatherly
Copy link
Member

By the way, why is SIGNATURES plural? In which case does it print more then one signature?

When there are default arguments such as

func(x = 1, y = 2)

you'll get

```julia
func()
func(x)
func(x, y)
```

Merging them all into a single signature is possible, but, just like with the printing of keywords, it can sometimes result in a slightly less readable signature I found.

I naively thought that this package works on strings representing the definitions

We can't really do that in a general way since the definitions may be defined in a for loop using @eval and a bunch of $ interpolations. I also wanted to avoid making the package too reliant on the actual source code so that it will still work in future versions of Julia where it would (hopefully) be possible to distribute precompiled packages without the source.

Sorry if this might sound unrealistic, I've got no idea how the current functionality is implemented and what's possible or not.

No worries, the package is quite new and hasn't yet been used all that much so there's plenty of improvements still needed. Input from other package authors is much appreciated, thanks.

Is it even technically possible to have per docstring switches like that?

Should be possible I think.

Wouldn't KEYWORDS have to deal with the lengthy defaults too?

Yup, it would. By formatting them in a list rather than a single code block it might give each keyword a bit more breathing room and so be more readable. I've not tried it out though, so couldn't really say for certain whether it would be any better.

@cstjean
Copy link

cstjean commented Apr 5, 2018

Note that we don't have access to the expression representing the signature, only the actual Function object, so it's not possible to just print out keyword = DEFAULT I believe.

Perhaps this comment is outdated, because as of 0.6, the full definition expression is available, and DEFAULT could be printed.

Core.atdoc!((args...)->(global dbg = args))

default = collect(1:100)
@doc """ Testing """ f(x, y=2; z=default) = "hello" * y

> (" Testing ", :(f(x, y=2; z=default) = begin  # In[5], line 4:
>            x + y
>        end))

Could be done in $(FULLSIGNATURES)

@tomchor
Copy link

tomchor commented Jan 26, 2023

Hi, I was wondering if there are still plans to make this a feature? I'm trying to use DocStringExtensions as a way to decrease manually-written code, but not displaying the default values is a deal breaker for me/us.

For example one of our functions' docstrings using DocStringExtensions shows up similar to

  Grid(
      architecture,
      FT;
      size,
      x,
      y,
      z,
      halo,
      extent,
      topology
  )

while the current manually-typed docstring is similar to:

  Grid([architecture = CPU(), FT = Float64];
                  size,
                  x = nothing,
                  y = nothing,
                  z = nothing,
                  halo = nothing,
                  extent = nothing,
                  topology = (0, 0, 0))

So as you can see a lot of information that would make the user's life easier is unfortunately lost.

I understand your arguments that this can become unreadable pretty quick, but I think having separate Abbreviations can help with that. So in addition to SIGNATURES and TYPEDSIGNATURES, we could have FULLSIGNATURES (with defaults but without types, thus more readable) and FULLTYPEDSIGNATURES (which would have the types as well as the default values).

Although any of the options cited in the comments above would be enough for me to finally start using the package.

Thanks for the good work!

@MichaelHatherly
Copy link
Member

Will likely be solvable after #133 is merged, where we can just use the documented expression directly to printout an easily readable representation of the defaults according to the original expression.

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

No branches or pull requests

4 participants