Stream: ideas

Topic: Move to a more structured approach of comments


view this post on Zulip Tobias Steckenborn (Jan 03 2024 at 11:41):

I'd like to suggest a more structured approach to comments compared to the current state of unassigned free text comments, which could benefit tooling building on top of it.

Examples for use cases can be:

Current Approach:

Doc Comments
Comments that begin with ## are "doc comments" which will be included in generated documentation (roc docs). They can include code blocks by adding five spaces after ##.

## This is a comment for documentation, and includes a code block.
##
##     x = 2
##     expect x == 2
Like other comments, doc comments do not affect the running program.

Example of TSDocs:

/**
 * Runs all the provided effects in sequence respecting the structure provided in input.
 *
 * Supports multiple arguments, a single argument tuple / array or record / struct.
 *
 * @since 2.0.0
 * @category collecting & elements
 */
/**
 * Returns an effect that will be executed at most once, even if it is
 * evaluated multiple times.
 *
 * @example
 * import * as Effect from "effect/Effect"
 * import * as Console from "effect/Console"
 *
 * const program = Effect.gen(function* (_) {
 *   const twice = Console.log("twice")
 *   yield* _(twice, Effect.repeatN(1))
 *   const once = yield* _(Console.log("once"), Effect.once)
 *   yield* _(once, Effect.repeatN(1))
 * })
 *
 * Effect.runFork(program)
 * // Output:
 * // twice
 * // twice
 * // once
 *
 * @since 2.0.0
 * @category caching
 */
/**
 * This function returns `true` if the specified value is an `Effect` value,
 * `false` otherwise.
 *
 * This function can be useful for checking the type of a value before
 * attempting to operate on it as an `Effect` value. For example, you could
 * use `isEffect` to check the type of a value before using it as an
 * argument to a function that expects an `Effect` value.
 *
 * @param u - The value to check for being an `Effect` value.
 *
 * @returns `true` if the specified value is an `Effect` value, `false`
 * otherwise.
 *
 * @since 2.0.0
 * @category refinements
 */

TSDocs uses tags within the comments for different sections or usages (https://tsdoc.org/pages/spec/tag_kinds/).

This can result in outputs such as:
image.png
image.png
image.png

view this post on Zulip Tobias Steckenborn (Jan 03 2024 at 11:50):

An example of tooling enabled by such an approach is https://tsdocs.dev/. It allows you to search for npm packages and displays a documentaton based on the TSDoc and Description of the package (see e.g. https://tsdocs.dev/docs/effect/2.0.0-next.62/index.html)

view this post on Zulip Agus Zubiaga (Jan 03 2024 at 13:12):

Roc being a statically typed language without reflection means that we can extract most of this information from the source and build a doc page that looks like the ones in the screenshot you shared without any changes to comments.

view this post on Zulip Agus Zubiaga (Jan 03 2024 at 13:14):

Oh, except for argument-level documentation, we would need structured doc comments for that.

view this post on Zulip Tobias Steckenborn (Jan 03 2024 at 13:18):

I wouldn't know how to structurally differentiate between a kind of summary, a detailed description, various examples and descriptions, sort of categorizations, potential cross references or argument/parameter level descriptions with the current approach. If such a thing is already possible, then scratch that. Right now it looks like a big lump of description that could be displayed on one page, with other pages simply being able to reference the name for e.g. a list based display of included elements. I don't know if that's enough to build a well-structured documentation or diverse editor helps with this approach.

If you just looked at the screenshots - most of that is also inferred, but e.g. the descriptions, category, therefor grouping an the like.

view this post on Zulip Agus Zubiaga (Jan 03 2024 at 13:35):

I guess I'm missing it. The second screenshot just seems to have a function signature, followed by a piece of text, and then generic types + parameters.

I see what you mean about categories in the first screenshot, though.

view this post on Zulip Tobias Steckenborn (Jan 03 2024 at 13:45):

Guess should have made it more clear that these are just partial samples. Other ones could be https://tsdoc.org/play/ (with e.g. the more complex samples, based again on https://tsdoc.org/, but another sample implementation). Sample for more details could be found on the individual tags (e.g. https://tsdoc.org/pages/tags/remarks/ and https://tsdoc.org/pages/tags/example/). That's just one reference though. In general the discussion I'd like to provoke is around the tradeoff of more structured documentation comments enabling more detailed tooling (e.g. parameter level hover descriptions in editors) vs the simplicity of the current approach. I see benefits in having a more complex, structured one.

view this post on Zulip Richard Feldman (Jan 03 2024 at 14:35):

I have to admit I'm default skeptical of the benefits of this sort of thing in general :sweat_smile:

view this post on Zulip Richard Feldman (Jan 03 2024 at 14:35):

I can definitely see how people could spend a lot of time filling out the fields (I certainly have in past jobs!) but I'm not sure where the payoff is

view this post on Zulip Richard Feldman (Jan 03 2024 at 14:36):

can you give some examples of use cases where you get benefit out of having this information be in a structured way?

view this post on Zulip Richard Feldman (Jan 03 2024 at 14:36):

for example: "I want to look up _____ but without _____ there's no way to do that"

view this post on Zulip Tobias Steckenborn (Jan 03 2024 at 14:45):

Yeah, though the examples will be of the simpler sort.

I want to quickly understand the expectations and descriptions of a parameter without leaving my context entirely and taking a look at the implementation of the function but without the granular description the only way to do this is to find the respective sections somewhere in the while function description if described in there. Contrary to that the editor could show me specific details for that parameter on hover if available in a structured format (see image for a simple example, where I assume the structure of the string could also be derived from the context itself though).
Tobias-Steckenborn-2024-01-03-at-15.41.222x.png

view this post on Zulip Richard Feldman (Jan 03 2024 at 14:49):

yeah so this is a good example of where I'm not convinced the payoff is worth the cost

view this post on Zulip Richard Feldman (Jan 03 2024 at 14:49):

if the docs begin with a 1-2 sentence description of what the function does, I can basically always read that and understand what each of the arguments do

view this post on Zulip Richard Feldman (Jan 03 2024 at 14:50):

so the payoff delta here is the difference between my reading a sentence or two about all the arguments vs one that's tailored to just the one argument, and I think that delta is small

view this post on Zulip Richard Feldman (Jan 03 2024 at 14:50):

whereas the delta in effort of annotating each individual parameter in all functions across the ecosystem is, I think, much higher

view this post on Zulip Richard Feldman (Jan 03 2024 at 14:53):

having seen ecosystems that do it both ways (e.g. TypeScript and Java do it with annotated params, Rust and Elm don't) I've had much more positive experiences with ecosystems that don't support this feature

view this post on Zulip Tobias Steckenborn (Jan 03 2024 at 14:53):

Yet nobody forces you to annotate each and every one. You can selectively describe them. Nothing prevents the other elements being described through inference or the like. Yet without explicit description you'll most probably not be able to even allow me to have the specificity of having it on the respective place.

Tobias-Steckenborn-2024-01-03-at-15.46.442x.png

If we construct that further and e.g. you expect a specific kind of String and want to give an example for that one, or want to include multiple differentiatable examples it gets more interesting.

view this post on Zulip Richard Feldman (Jan 03 2024 at 14:53):

Tobias Steckenborn said:

Yet nobody forces you to annotate each and every one.

if the feature exists, there will be pressure to use it

view this post on Zulip Richard Feldman (Jan 03 2024 at 14:54):

for example, I can imagine issues being opened on repos saying "hey can you please annotate each argument like [other package] does? I want that level of specificity in my editor integrations!" :big_smile:

view this post on Zulip Tobias Steckenborn (Jan 03 2024 at 15:15):

Yeah, benefits and drawbacks as usually. Looking at that sample basically the same was done, but without the automatic creation of the structure or any benefits such a structure would yield: https://github.com/roc-lang/examples/blob/58e34714d0177e9b09f664a08218246025f17c86/examples/GraphTraversal/Graph.roc#L44-L49

It just seems to me that currently you'd just be able to render out a list of commented things without any context or categorization if you'd e.g. automatically create a documentation. To me some sort of logical grouping when searching for something is helpful.

Let's take this as an example:

2024-01-03-at-16.10.542x.png

With the current approach it seems to me as the only thing we could do in Roc is list out the all the functions in e.g. an alphabetical order without any logical grouping. If something is marked as deprecated but maybe included for compatibility reasons it's not apparent but by reading through all the body and find it somewhere within. Also (as an example with the conventions of tsdoc) the summary could be shown here without all the details to skim and find the right function to use.

Now let's assume I found the function I want to use. There would be no way to parse that into a structured documentation splitting examples from the overview or parameter descriptions near the parameters details that might be derived via the types. So I would most probably have one large chunk of ?markdown? followed by the information available via the types and the like.

Contrary to that a structured approach would allow you to create such docs:

2024-01-03-at-16.13.042x.png
2024-01-03-at-16.13.292x.png

Again the created documentation here and the author of the package are unrelated. The author of the package uses it in their own docs:
https://effect-ts.github.io/effect/effect/Predicate.ts.html#issymbol

view this post on Zulip Richard Feldman (Jan 03 2024 at 15:18):

optional groupings seem potentially reasonable to me, and they could be done in exposes e.g.

exposes [
    ## alternatives
    foo,
    bar,
    ## caching
    baz,
    blah
]

view this post on Zulip Richard Feldman (Jan 03 2024 at 15:18):

deprecated is definitely something I want to support :thumbs_up:

view this post on Zulip Richard Feldman (Jan 03 2024 at 15:24):

when I look at these two pieces of documentation side by side...

2024-01-03-at-16.13.042x.png
Screenshot-2024-01-03-at-10.24.11-AM.png

view this post on Zulip Richard Feldman (Jan 03 2024 at 15:24):

I have a major preference for the second one. It's straightforward and uncluttered.

view this post on Zulip Richard Feldman (Jan 03 2024 at 15:26):

The "Parameters" section in the first example is a net negative to me as a reader of the documentation; it is not helping me, it's just repeating information I already knew.

The "Examples" heading is also unhelpful. I can tell it's an example from looking at it.

The "Since" section is also irrelevant in almost (but not quite) every situation.

view this post on Zulip Richard Feldman (Jan 03 2024 at 15:27):

basically I think if Roc documentation looked like that, it would be a significant step backwards! :sweat_smile:

view this post on Zulip Richard Feldman (Jan 03 2024 at 15:29):

overall I think this should be multiple design discussions (about individual use cases, like deprecation and putting headings in documentation for related functions) instead of one design discussion (more structured comments), each motivated by use cases

view this post on Zulip Richard Feldman (Jan 03 2024 at 15:31):

honestly I'm pretty resistent to structured doc comments in general, because I think they lead to documentation that looks more like the first screenshot than the second, and I don't want Roc to move in that direction!

view this post on Zulip Tobias Steckenborn (Jan 03 2024 at 15:33):

Hard to argue based on my lack of Roc knowledge. Especially looking at more complex cases such as e.g. expected input is a string, but of a specific kind and the like or multiple different examples contained.

I can just say that I really like to only see what's relevant to me in that context, so if I'm looking at a parameter I really prefer just reading what's relevant to that parameter (as an example). Contrary to that when searching for the correct function to use I don't want to read through all the details of all the functions of a package.

But a lot of that is speculative, until there are larger packages, potentially building on top of each other.

view this post on Zulip Richard Feldman (Jan 03 2024 at 15:34):

personally I don't see this as a Roc thing

view this post on Zulip Richard Feldman (Jan 03 2024 at 15:34):

I think I would like TS and Java docs more if they focused on being concise and straightforward instead of being structured :big_smile:

view this post on Zulip Richard Feldman (Jan 03 2024 at 15:35):

I also think it creates the wrong incentives for package authors

view this post on Zulip Richard Feldman (Jan 03 2024 at 15:36):

Tobias Steckenborn said:

if I'm looking at a parameter I really prefer just reading what's relevant to that parameter (as an example).

I totally appreciate that, although I don't think the benefit is worth the cost in that particular example :big_smile:

view this post on Zulip Tobias Steckenborn (Jan 03 2024 at 15:38):

Yeah, just didn't see that as a lot of additional cost as you could still render it out as you please. It's just that right now e.g. here https://github.com/roc-lang/examples/blob/58e34714d0177e9b09f664a08218246025f17c86/examples/GraphTraversal/Graph.roc#L44-L49 technically it's doing the same thing, but completely text based without the benefits behind it. Never the less got your point. Let's move that discussion until somebody has further arguments to weigh in. Otherwise one might pick singular elements but bury this one :D

view this post on Zulip Richard Feldman (Jan 03 2024 at 15:39):

cool, sounds good! :thumbs_up:

view this post on Zulip Tobias Steckenborn (Jan 03 2024 at 15:47):

Just as I don't have one such example available, what would I need to do to look at a more complex sample, taking e.g. a configuration (potentially with a branded type [if there's such a thing] for e.g. url) and returning another function?

Wondering how that would compare if there's something like an API client that you construct, allowing you to call different HTTP methods on different endpoints based on some base url and e.g. some common elements such as authentication you provide in an earlier step.

Or is that not a valid case for Roc?

view this post on Zulip Richard Feldman (Jan 03 2024 at 15:51):

I think that's a separate design question altogether :big_smile:


Last updated: Jun 16 2026 at 16:19 UTC