Adopt the SciML Style Guide for Julia Base and Standard Library?

After thinking about docstrings from another post, I was wondering if the Julia Style Guide, particularly for Core, Base, and the standard libraries should be further specified, particularly for docstrings.

Perhaps a good place to start would be the SciML Style Guide. I’m particularly interested a more detailed convention for documentation. For example, should exported or public Base functions follow the example below taken from SciMLStyle?

"""
    mysearch(array::MyArray{T}, val::T; verbose = true) where {T} -> Int

Searches the `array` for the `val`. For some reason we don't want to use Julia's
builtin search :)

# Arguments
- `array::MyArray{T}`: the array to search
- `val::T`: the value to search for

# Keywords
- `verbose::Bool = true`: print out progress details

# Returns
- `Int`: the index where `val` is located in the `array`

# Throws
- `NotFoundError`: I guess we could throw an error if `val` isn't found.
"""
function mysearch(array::AbstractArray{T}, val::T) where {T}
    ...
end

The one thing I might add here would be a Implements or Interfaces section.

15 Likes

The answer is YES. Early on, I believe the Julia devs were conservative and didn’t want to be overly prescriptive. The language has clearly matured, and the inconsistencies in docstrings and documentation now outweigh the theoretical pain from over-prescription.

It’s fine to be opinionated at this point, and to have guidelines for core/base. Likely there may be bits deep in the repo that’ll take years or never get updated, and that’s fine. But might as well standardize from now on and set an example for all to follow.

SciML has done a great job of leading the way. AFAIK there haven’t been any revolts. I would go as far as to recommend similar guidelines for all users. I often suffer pangs of doubt “am I doing this the right way?” that are not resolved by websearch. It’s okay to state an opinion without it sounding like Zen of Python. And eventually maybe even adopt the SciML guidelines on interfaces…

4 Likes

100% agree.

On top of that I would like this to hook into Documenter.jl, so it can read the docstring and nicely format it for me when rendering the docs. Python docs usually do this and it looks much cleaner in my opinion.

6 Likes

I think there are many good points in the SciML style guide, but I do not agree with this one in particular:

Prefer to not shadow functions

Two functions can have the same name in Julia by having different namespaces. For example, X.f and Y.f can be two different functions, with different dispatches, but the same name. This should be avoided whenever possible

in my view, trying to consolidate kinda-similar-kinda-not-really-the-same methods into the same function often leads to a whole lot of bugs that could be avoided if we were more willing to namespace functions per package!

5 Likes

I suspect that is mis-worded. SciML has overloaded solve everywhere, so do they intentionally re-use method names for a general concept. I believe they mean a couple things: Don’t use the same name for very different concepts, and perhaps don’t use a highly ambiguous or unhelpful name. And of course we can always use the module as a namespace, or import to be more explicit.

1 Like

This is one of the things I noticed the most coming from Python. I’m not sure if its just because I have not dug deep enough in Documenter.jl or not, but at a surface level I didn’t notice a way to neatly document arguments and return types following the Documenter.jl guide. I really like the SciML style and it would be great to see it rendered like this into the generated documentation. It would also be good to see an example of a more complicated docstring make its way into the guide as well. When I first read it I wanted to know how to handle arguments and returned types but just assumed that wasn’t the norm in Julia.

3 Likes

I strongly prefer SciML’s naming principles. The style awordandanotherword or even worse abbrvwrd are quite unnecessary in a world with tab-compilation.

4 Likes

The main criteria I have here is whether the methods follow a common functional interface or not. If X.f always takes two arguments and Y.f always takes three arguments, it seems questionable if these are really methods of the same function. That’s very simplified. It really depends on type abstractions and if varargs are part of the interface.

1 Like

It’s all handwritten markdown right now, and there is no single agreed upon format to document function arguments. That’s why, in my opinion, Julia API docs can feel quite messy. Each project does it differently. I frequently run into API docs that haven’t documented function arguments at all, and everything is just Any according to the docs (but it never is)

I did some digging a while back and found this relevant discussion: Argument-specific docstrings or comments, unfortunately that never got any followup.

So for now my suggestion would be to:

  1. Pick a style guide you like. SciML, Blue, YAS.
  2. Ensure you follow the styleguide by using JuliaFormatter.jl
  3. Apply style-specific formatting using custom CSS.
3 Likes

Copying over some thoughts from a different thread:

I think one of the problems with the Julia documentation is that dozens of functions are documented on the same page, which incentivizes short docstrings. Each generic function should have its own documentation page.

On a somewhat related note, a generic function should only have one meaning, i.e. docstring, for each arity, so other modules that extend a function shouldn’t have any new docstrings unless the new method adds a new arity.

10 Likes

I do like attempts to programmatically generate all or some of docstring content like Jieko.jl and DocStringExtensions.jl, and I’ve written my own small adjacent functionalities for my own packages. Too many times I’ve had to access a package’s code to understand exactly what is going on in a method signature because the docstring wasn’t clear enough, or was missing usage information.

Latest example was in the excellent package CoherentNoise.jl for sample where it states the arguments are of type Real but it wasn’t working for my case of mixed AbstractFloat and Integer instances. I dig into the code to find out that the arguments are all of type T with where {T <: Real} so all arguments needed to be the same type.

Granted this type of problem is somewhat diagnosable by the MethodError that gets thrown, but I wasn’t in the clearest headspace at the time. And this problem could be all the more confusing for a beginner.

I think it’s important we start agreeing on some standardisation of docstring together as a community now. Like others have said, Julia has matured enough for us to start thinking about this.

2 Likes