-
-
Notifications
You must be signed in to change notification settings - Fork 5.5k
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
formatting conventions for function documentation #8966
Comments
I've wondered if we'd need automatic stubs for documentation. One of the things I most like about R's documentation system is that individual-level documentation of every single parameter of a method. I'd really like to see that kind of detail in most documentation for Julia as it matures. |
Yes, having the signature automatically is certainly nice. Also, some structure and style that is common across Base and eventually across packages is also good to target for. Should we try to pick a few functions and establish what documentation should like ideally for those, and then bake that in? |
Automatically displaying the signature would be nice in some cases, but not all; e.g. if you define your user-level function as One thing I'd definitely like to see is some form of one-line summary convention. We can do all sorts of nice things with that, like intellisense-style autocomplete in IPython/Juno and even live, smart code hints, which I have a very rough prototype of: That said, I'm also leaning towards letting standards evolve naturally rather than enforcing something early on. The result is likely to be better and using markdown means it's pretty trivial to pull out structured data even if the conventions are fairly loose. |
One convention I've thought about from time to time is to use long descriptive argument names. We do have a tendency to abbriviate especially on some additional method definitions, however, which is convenient; maybe we could have some system where |
Perhaps see numpy for inspiration https://github.com/numpy/numpy/blob/master/doc/example.py https://github.com/numpy/numpy/blob/master/doc/HOWTO_DOCUMENT.rst.txt. Numpy basically uses markdown but doesn't do anything special to extract sections:
perhaps this could be lowered/expanded to something like (although these probably need to be ordered):
In the syntax of #8588 (comment). I think having this making actual metadata rather than just a convention will be useful... this way one could, say, extract all the references in a module, or highlight the doc of the current parameter as you type, or toggle through just code examples. |
These are the sections @milktrader suggested. These seem like a great start.
|
In addition to Arguments, we need Returns as well. |
Compare to the documentation we have now, where a typical function has a one-paragraph description. Would it really be readable if every single one of these descriptions were expanded into 7 subsections complete with headings? I'm skeptical. |
Coming from R, I find the current documentation a little too terse. For simple functions, I agree that leaving out many of those subsections seems reasonable. But for functions with even the slightest bit of subtlety (e.g.
|
@stevengj If we have section templates, we can choose different levels of verbosity for the command line help (just show description and usage), and the manual which has all sections. Matlab also does more than what we do currently, which helps when one is new to the system. |
Fair enough. |
I've always wished one could click somewhere and find out about numerical notes ....when |
I have always wished that too. With the Julia community, we actually have the skill to pull this off, and hopefully even create something that is more comprehensive and better than what any other system of this sort has done before. |
(Ideally, just click to edit the documentation and then submit a pull request.) |
I implemented documentation for the Maxima CA (as third party code), Much of this is already being done for Julia, but I wanted to get some ideas out. I did it all myself; it would great to see Julia collaborators do something similar and more ambitious, and do it right. https://github.com/jlapeyre/mext/tree/master/packages/defmfun1 Examples of using the system are in several packages in the sibling directories. I (almost) never write things like "foo(x) does...", or " takes a string x as input, and returns ...", or "Examples: ". The function name, arguments and types and special restrictions, examples, and other features are all meta data, when possible extracted automatically or with minimum specification. It is used to generate uniform, consistent documentation. The same meta data is used for argument checking and for printing (or suppressing, statically or dynamically, globally or per function) uniform, consistent error and warning messages. Here is (outdated) html output of the documentation for several functions that I wrote with this system. http://www.johnlapeyre.com/thirdparty.html Many Maxima user-level functions are implemented as (Common) lisp functions. It is standard practice to handle argument-checking, argument pre-processing, error messages, documentation, etc. in an ad hoc way. I wrote a macro, 'defmfun1' to wrap 'defun'. The macro arguments ("directives") affect the behavior of the function as well as the generated meta-data. All the special behvavior can be omitted, or easily turned off either in the definition, or at run time. It is typical for Maxima functions to check arguments, kind of like Mathematica. This is done in an erratic and ad hoc way. I liked the more-or-less consistent Mathematica error (or warning) messages and getting them easily and consistently was attractive. I also like the uniform and consistent Mathematica documentation. I used the Mathematica messages as a model. Here are up-to-date examples:
Interactive session. Print doc and try examples:
Here is code that generates examples in the documentation. The
The plain text format is:
There is a table of argument specifications used for inserting code, for argument https://github.com/jlapeyre/mext/blob/master/packages/defmfun1/arg-spec-definitions.lisp This kind of table would probably be used differently with Julia, eg called I implemented uses for some other meta-data that may be relevant for
I tried to find an simple way to include the data in or near the function definition. I only used s expressions, and was only partially successful in making readable entries, although I think with effort this could be improved. Then, using the data (or not!) is a separate issue. Some issues/differences with Julia Building the doc structures significantly slows compilation. I compiled the lisp code, so the meta data is only collected and processed once. Does not work directly with jit. Maybe have a flag on installation that processes the meta data and writes to a per module database. For normal use the doc macros are ignored. But, this is a much more complicated installation than just copying jl files. multiple dispatch: how to handle documentation coding and use when methods are added for a function? Where does the documentation belong if the methods really are doing very different things. And you can't extract meta data for docs as easily from a parameter list if you use multiple dispatch rather than argument conversion within the function. Using logic on all existing methods sounds complicated. Mathematica dispatches on patterns, how do they do it ? |
Any chance of adding something like Mathematica's REPL-aware function templates within the doc structure? Their notebook front end parses the "usage" docstring, and provides a template when you use the "make template" shortcut (cmd-shift-k on OSX), e.g. Another thought is to have the docs include more explicit argument definitions or have clearer parsing rules, rather than MMa's ad hoc method. This could potentially allow for things like tooltips pop up when you hover over an argument x to show expanded documentation like "a numeric vector". One annoyance with Mma is that once you are inside the template, you can't hover or go back to the usage string to be reminded about what x was. With a slightly stricter documentation format, it's possible to do more at the REPL level. |
In #9447 @MichaelHatherly @one-more-minute @hayd very kindly humored me as I ranted about the features I wanted in documentation. I have just reformatted in IterativeSolvers: rlinalg.jl and rsvd.jl the documentation of It's really nice to see help for functions I wrote! I hope my usage helps clarify why I would like inline cross-references, equation rendering and bibliographies. |
I was having a play trying to put together a MetaDoc type a'la @stevengj in #8514 (comment) and #8588 (comment), it doesn't seem to play well with Anyways a gist is here: https://gist.github.com/hayd/bdddb51dc7df89b9a24e Thinking about it may be that you could just extract sections from the text i.e. lower @jiahao's docstrings into MetaDoc... (kind of docopt-style). There's some discussion about Returns section (and how you could use this) in PR to prepend signature info to the help message: #9838. |
I hadn't realised that Docile has a meta object, but that didn't make it to base. @MichaelHatherly IMO Docile.meta ought to be in base, having two levels of documentation (one in Base and one in Docile) seems strange. getting it in base would help flesh out what meta is and get it working (e.g. it doesn't work with help for me in 0.4 - following the examples in the readme :( ). Pretty please can we have meta! |
@hayd, I think I might have added From the looks of your gist that's basically all there. Not sure about the rendering trouble you're having; @one-more-minute is the best person to ask about that. Some differences I can see: naming (I can easily change names in Docile if we settle on |
@MichaelHatherly You may be able to use the compat module to support 0.4 syntax on 0.3.... ? TBH I'm not sure what syntax is best here going forward anyway, perhaps others have some ideas, but 💯 to getting meta in. :) |
I want to point out that extensions, like So once 0.4 is out there's really no reason Docile.jl can't be compatible with it. I'm sort of hoping it will live on as a way to have all of the great "advanced-mode" doc features that it currently supports, including things like metadata. |
I've been writing some docs with this system and, alongside metadata, I would find very useful to have a way to insert the function's signature into the docs automatically. Actually, the same for constants (insert their types into docs), types (insert their supertypes), macros and generated functions, etc. Maybe something like: @doc """
$signature$
Foo the living hell out of an Int
""" -> function foo(x::Int) So that:
Also, I really believe metadata for docs should be on Base. This would incentive developers to write richer documentation from start, while guaranteeing good documentation on how to do this, and a single stardard way to do it. |
There;s been some major changes to Docile of late, which parses
even if there's no I think there is an issue about signature (and I had a PR rejected), IMO it should always be shown. `$ wouldn't work as it's already used for latex, but there may be some other options for similar things... I think the metadata will work itself out, now that Docile doesn't need |
Well, why not just use the javadoc/doxygen/etc. tags (they are pretty standard), instead of coming up with something julia specific? ##\brief Brief description here
#
# detailed description
# \param[in] str::AbstractString String to be munged
# \param[out] buf::Vector{UInt8} Output buffer
#
# \returns Bool if string was valid or not
# \throws ArgumentError (if str is empty) Doxygen supports Markdown, and the comments can be easily filtered to remove the I think this would be better than everybody coming up with their own incompatible style, which is what is going on now... |
Parsing markdown to extract metadata sounds awesome. We could parse anything before an (sub)title as a overview end xtract other section based on title names. For parameters, I believe we should have a standard way to do it, maybe a markdown list of parameters and their types/descriptions:
Would get us something like: :arguments => Dict(:x => "A number to be fooed", y: => "Simply *anything*" ]) Down the road we could use the upcoming Ordered Dicts to provide the order of these parameters while still using a Dict. An IDE could, then, use this info (alongside function's signature) to provide tooltips for each parameter as we type them (like their types and descriptions). |
Yes, but just using the \param tag, with the optional [in], [out], [in,out] attributes, makes it really easy to pull out all of that and create the metadata, for \returns and \throws as well. |
Instead of an OrderedDict, what about the NamedTuples that I've heard about? |
This may work, but I'd prefer not to add new syntax just to obtain metadata. More syntax to document, test and remember. |
@prcastro Yes, something like this would work well. The more I think about it the more I dislike the idea of specialised syntax like doxygen/javadoc. I mean, I get it – we're programmers, and writing things that computers can parse and manipulate Just Feels Right. But doc strings have to be designed for humans first – and humans, particularly ones new to programming, are a lot more comfortable with paragraphs of text than noisy syntax trees and On top of that, we already have two syntaxes – Julia and Markdown – and we should be able to use them to specify anything we want (in the limiting case, by splicing a metadata dict into the docstring, for example). As long as structured data is a nice-to-have rather than a make-or-break, there's no way to justify adding a third syntax for people to learn on top of that. |
Exactly, things become even more difficult to the enduser when you pile up more syntax. Afterall, people searching for that kind of power could find it on packages like Docile. Base should have just a simple metadata system, that is as natural and as unobtrusive as possible to newcomers. Would the overhead of parsing markdown to obtain metadata be a problem? |
I don't think so – we already parse markdown to display it so it's just a case of looking over the structure for metadata lists etc. Should be pretty easy, really. I should clarify also that Base's default doesn't prevent anyone using doxygen or whatever if they really want. You can just use your own string macro:
|
@one-more-minute Ha! I already have a dox"..." macro! Might I say, "great minds think alike"? 😀 @prcastro You'd still have to come up with some new syntax to say if something is a parameter, a return value, or what errors are thrown... my point is simply, there is already a syntax that is pretty much a de facto standard, why not use that? I think a lot of people would probably be at least familiar with it. I guess, if you actually do make sure that everything is correctly parsed, and you can produce the metadata for: brief description, full description, parameters, return value(s), and errors thrown, |
For what it's worth, I'm 100% with @one-more-minute on this – adding doxygen syntax to the mix is causes more problems than it solves – and we want to support people before machines. The issue with generic documentation systems like doxygen is that they never quite do what you need, so you end up in this close-but-no-cigar situation until you throw in the towel and build/design something custom that's really tailored to your specific needs. Julia is unusual enough as a language that the chances of something "standard" like doxygen working really well for it seems negligible. |
You maybe missed my comment elsewhere, I am also now 100% behind @one_more_minute's excellent idea of parsing the meta data out of the doc strings, from which I could generate a file in a form doxygen could understand, to get all the x-references out of the code, even x-referencing with the C source files in julia/src |
I wasn't addressing you specifically. |
Extracting metadata from markdown has the benefit of a graceful failure. Also checkout https://github.com/MichaelHatherly/Lexicon.jl ...perhaps we can use that to build the docs in the future (without migrating it to base!!) |
@alanedelman wrote Last night I put an http link inside of @doc inline function documentation. It half worked. |
@JeffreySarnoff they're called autolinks. I did a PR for that a while ago. There's a way to go for full commonmark compat. |
@hayd clearly appropriate There is a watershed of benefit to Julia when, as one designs, experiments, codes, and dreams there are co-available threads of insight to push and enagement to pull. Soon there are others pulling and pushing through shared threads. This self-magnifies, setting a place for Julia in many, many places. |
Right now, the
@doc
help suggests;In method documentation, wouldn't it be much more satisfactory () for the
help
command to automatically prepend the signature forfoo
before the documentation output as needed?In generic-function documentation (e.g. documentation for
sum
in all its forms), obviously this is not possible (since there will in general be multiple possible signatures). However, we should establish some convention for what the documentation should look like.The text was updated successfully, but these errors were encountered: