Not yet.
Happy reading: https://github.com/JuliaLang/julia/issues/3988 :)
I really like godoc – that's basically what I want plus a convention that the doc strings are markdown.
The issue is that you want to have all code documentation show up in REPL. In the GoDoc approach, this might require an explicit "build" step -- which is a non-trivial cost in usability.-- John
Could we not have both, in a way? A sensible convention for comment-based documentation using markdown, which I expect covers the vast majority of usecases (being human-readable plaintext that converts to rich text). During compilation that documentation is converted and added to the global dictionary of metadata you propose.
As we're starting to get better ideas for a documentation system, two questions I have are how we do two things:(1) Handle documentation of generic functions and their specialized methods without requiring documentation of all specialized methods.
(2) Handle documentation of functions that being generated by macros.
We don't need flexible documentation – we need one simple documentation system that works.
And if you sacrifice flexibility, you might easily end up with something that works for now, but is an annoyance in a few years. (It is really hard to add more structured information into Python docstrings, for example.)
I think putting documentation in something that is not syntactically meaningful -- comments -- will get more and more annoying, because you'll end up inventing more and more ad-hoc rules for how to associate which documentation with which object
e.g. how do you associate the docstring comment with a constant?
with a Function as opposed to a specific method
Not to mention that the documentation system will have to decide which comments are docstrings and which comments are just internal comments by programmers who didn't intend for the comment to be an end-user doc.
Is the constant publically visible? Then it's probably top level, so a comment directly above it works. That's what Go does.
How would documentation handle type information for the arguments to a
method? There are 3 possible sources: the comments, the text of the
function arguments (e.g. someArg::FooType), and the compiler.
Then one could use the existing Julia syntax for substituting values into the documentation, like:# This is a comment. 1 + 2 = $(1 + 2)
I don't have a strong opinion on this topic, but I really don't understand why this is better than using directly:@doc "This is a doc string: 1 + 2 = $(1+2)"What is lost when using a string compared to comments?
doc beginlots of documentation, blahblahend
doc Foo is a function with ....
doc rst Using some restructuredtext here.
The primary difference to me is the ease of expansion that comes along with comments. Ie, if there is already one line of comments, I just hit newline in my editor, and it automatically adds a new comment leader and I can add an additional thought to the comment. Whereas with strings and markup, I have to go and tidy up the ending quotations.
But if we're proposing modifying the parser anyways, then we could get the best of both worlds with a doc keyword that is line terminated or block terminated just like the let keyword:doc beginlots of documentation, blahblahend
Why is begin...end better than """....""" ?
I really think that embedding documentation in comments is a mistake. Documentation needs to be a part of the language, included in a semantically meaningful way, not an add-on that is semantically meaningless (comments).
@doc """commentary"""function ...
# commentaryfunction ...
Hi Francesco,
Docile.jl partially covers what I think you're wanting out of your docstrings, namely testing examples for correctness. I've been thinking about exporting the docstrings to ijulia notebooks which might provide a more interactive experience in some cases.
##
# docstring
#
# Metadata {
# key1 => value1
# }
#
# Examples
# ========
#
# julia> f(3)
# 9
#
function f(x)
x^2
end
#=
docstring for square number [references.wikip]
.metadata {
key1 => value1,
key2 => value2,
...
}
Examples
========
julia> f(3)
9
.references (
wikip : https://en.wikipedia.org/wiki/Square_number
)
=#
function f(x)
x^2
end
Docile.jl looks great, but I think that the API should be made into comments. One of Julia's goals is to have a simple syntax that even people who are not acquainted with programming can easily understand.
I believe that a tagged comment is much more readable than a block introduced by @doc or doc.
Docile.jl looks great, but I think that the API should be made into comments. One of Julia's goals is to have a simple syntax that even people who are not acquainted with programming can easily understand.Python, despite using docstrings, is a great example of a language having "a simple syntax that ... understand"
I believe that a tagged comment is much more readable than a block introduced by @doc or doc."Much more readable" is maybe a bit exaggerated, can you explain why you believe so?
module PackageName
using Docile
@docstrings # Call before any `@doc` uses. Creates module's `__METADATA__` object.
@doc """
Markdown formatted text appears here...
""" {
# metadata section
:section => "Main section",
:tags => ["foo", "bar", "baz"]
# ... other (Symbol => Any) pairs
} ->
function myfunc(x, y)
# ...
end
@doc "A short docstring." ->
foo(x) = x
end
Thanks for having a look at Docile.jl. I’ll try to explain some of
my decisions regarding it’s design.
Introducing a new AST object:
Having something built into the language would be great and I’d
definitely support that. There’s been some discussion, I think, about
doing that - probably in this thread or another from earlier, perhaps on
GitHub.
I needed something that works now and wouldn’t need changes to any
internals, hence the use of macros for this.
Using comments rather than strings:
A much earlier version of Docile.jl did do this, in part, but what I
found was that since comments get discarded during evaluation of the
code this required a separate run to capture documentation. I may have
missed a few tricks to get that to work though.
Another gripe I have about using comments: unless you use some special
syntax/tag (such as the extra #
character) to denote what is actually
documentation and what isn’t then commenting out code temporarily
could cause problems if docstrings are parsed by Julia “as valid AST
objects”. Using a docstring “tag” to avoid this would work I think, so
long as it visually distinguishes plain comments from docstring
comments.
Metadata in the docstring/comment:
##
# docstring
#
# Metadata {
# key1 => value1
# }
#
# Examples
# ========
An earlier version I had did embed the metadata directly into the
docstring using the YAML.jl package. Switching to an actual Dict
simplified the code and also makes it easier to generate metadata
programmatically if necessary.
Readability of @doc
:
I think that this probably just comes down to personal preference for me - I’ve not done an extensive comparison between different syntax.
@doc
introduces a docstring and seems pretty straightforward to me. It
explicitly states that what follows is documentation. That example from
Docile.jl could probably do with some simplifications since that metadata
section looks terrible if I’m honest. Something like the following might be
better as an initial example:
module PackageName
using Docile
@docstrings # must appear before any `@doc` calls
@doc """
Markdown formatted text goes here...
""" ->
function myfunc(x, y)
x + y
end
end
And then leave introducing metadata until after this since I’ve found
metadata to not be needed for every docstring I write.
I’m not sure about the “clearly visible bounded block” though, what in
particular could be clearer? I’m asking since I’ve been staring at these
for a while now and have become quite accustomed to them.
— Mike
There will always, however, be more documentation that doesn't affect the behavior of the code. I'm not even sure what it means for that kind of documentation to be "semantically meaningful" – you mean that it has a specified format means something?
doc"
Markdown formatted text goes here...
" ->
function myfunc(x, y)
x + y
end
Well Leah’s already answered this while I was fighting with my formatting, but here’s mine anyway :)
Welcome to the shed :) I really like that syntax and if it’s possible to get it to work that would be really nice.The problem is that a @doc_str
macro wouldn’t capture the Expr
that is being documented. See the dumps below:
julia> dump(quote
doc"
Markdown formatted text goes here...
" ->
function myfunc(x, y)
x + y
end
end)
Expr
head: Symbol block
args: Array(Any,(2,))
1: Expr
head: Symbol line
args: Array(Any,(2,))
1: Int64 3
2: Symbol none
typ: Any
2: Expr
head: Symbol ->
args: Array(Any,(2,))
1: Expr
head: Symbol macrocall
args: Array(Any,(2,))
typ: Any
2: Expr
head: Symbol block
args: Array(Any,(2,))
typ: Any
typ: Any
typ: Any
julia> dump(quote
@doc """
Markdown formatted text goes here...
""" ->
function myfunc(x, y)
x + y
end
end)
Expr
head: Symbol block
args: Array(Any,(2,))
1: Expr
head: Symbol line
args: Array(Any,(2,))
1: Int64 3
2: Symbol none
typ: Any
2: Expr
head: Symbol macrocall
args: Array(Any,(2,))
1: Symbol @doc
2: Expr
head: Symbol ->
args: Array(Any,(2,))
typ: Any
typ: Any
typ: Any
@doc_str
takes the contents of the string in as an argument (you can pass some flags in as well, see the Regex
syntax for examples) and not the Expr
appearing after. The @doc
macro takes a varargs macro doc(args...)
and so can capture everything after. The trick is the ->
which does “line continuation” (or something like that).
The ->
also allows Docile to capture line number information of things other than method definitions. If you’ve looked at the generated docs for Docile you’ll see that everything has file and line number information provided.
Glad you’re excited. Give me a shout if you run into any issues.