# The challenges of documenting generic functions

**URL:** <https://discourse.julialang.org/t/the-challenges-of-documenting-generic-functions/103198>\
**Category:** General Usage\
**Tags:** documentation\
**Created:** [August 24, 2023, 9:18am UTC](https://discourse.julialang.org/t/the-challenges-of-documenting-generic-functions/103198 "2023-08-24T09:18:23Z")\
**Posts on this page:** 5\
**Page:** 2

<div class="post-metadata">

**Author:** ![Tamas\_Papp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamas_papp/32/25949_2.png) [@Tamas\_Papp](https://discourse.julialang.org/u/Tamas_Papp)\
**Post date:** [August 29, 2023, 7:27am UTC](https://discourse.julialang.org/t/the-challenges-of-documenting-generic-functions/103198/21 "2023-08-29T07:27:43Z")

</div>

> [@ryofurue](#):
>
> All experienced julia programmers have internalized _concepts_ like “iterables” and “indexables”, and so, they _naturally_ expect any “indexable” to work as the `A` argument of `findall(predicate, A)`.

You may be talking about [interfaces](https://docs.julialang.org/en/v1/manual/interfaces/). They are the right level of abstraction for some APIs, but there is nothing that requires that an API conforms to a particular interface. Nothing requires that all methods conform to a single interface. It may be bad API design, good API design, historical accident, etc.

In particular, collections evolved in Julia very gradually, and a lot of the inconsistencies you see are of historical origin. You will find that the [collections and data structures](https://docs.julialang.org/en/v1/base/collections/) part of the manual enumerates a couple of “loosely defined” interfaces, in contrast to the interfaces section I linked above, and eg for `findall` & friends methods were added as the language evolved, eg `findall(c::AbstractChar, s::AbstractString)` came with Julia 1.7.

I agree that it is frustrating, but I think that small, piecemeal changes will be received better than large conceptual reorganizations. Eg it would be a worthy goal for a PR to clean up the docs and concepts for a small set of methods that are related.

For example, all methods of `findall` at the moment seem to be _conceptually_ equivalent to

```julia
findall2(needle, haystack) = 
    [key for (key, value) in pairs(haystack) if neddle == value]

```

with the caveat that the output only matches the sorting when `pairs` is ordered. Of course the implementations are optimized, but you will find that the only thing that is conceptually needed for it to work is `pairs`.

But this is just my rational reconstruction, and while it happens to match the default method, it is not documented. So maybe it should be?

A lot of functions in Base could benefit from a little love along these lines. I think that PRs are ideal for that.

---

<div class="post-metadata">

**Author:** ![fph](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/fph/32/17159_2.png) [@fph](https://discourse.julialang.org/u/fph)\
**Post date:** [August 29, 2023, 7:57am UTC](https://discourse.julialang.org/t/the-challenges-of-documenting-generic-functions/103198/22 "2023-08-29T07:57:03Z")

</div>

> [@lmiq](#):
>
> The functionality exists:

But then you are adding a default method to `f`. This choice might complicate debugging, because code that should have failed now unexpectedly returns `1`.

And would this also cause type instability? If all other methods of `f` return a `String`, for instance, this might prevent the compiler to infer the correct return type.

---

<div class="post-metadata">

**Author:** ![ryofurue](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ryofurue/32/24531_2.png) [@ryofurue](https://discourse.julialang.org/u/ryofurue)\
**Post date:** [August 29, 2023, 8:07am UTC](https://discourse.julialang.org/t/the-challenges-of-documenting-generic-functions/103198/23 "2023-08-29T08:07:45Z")

</div>

> [@Tamas\_Papp](#):
>
> You may be talking about [interfaces](https://docs.julialang.org/en/v1/manual/interfaces/).

Yes! That is the kind of “concepts” I have in mind.

> [@](#):
>
> They are the right level of abstraction for some APIs, but there is nothing that requires that an API conforms to a particular interface. Nothing requires that all methods conform to a single interface.

That’s the very reason that I keep saying “convention”. Nothing “requires”, but

- A convention will “encourage” its adoption.
- In order to indicate the “intention” of the API, we can use the terms and ideas in the convention in the description of our APIs. Then, deviation from the “intention” will be discouraged.
- When we write a new function, we will be encouraged to use the concepts in the convention.

So, yes, I’d like to enhance the “interface” document, so that a newcomer will read it and understand it. If the official documentations use the ideas and terms in the interface document, it will become more readable to newcomers. Also, newcomers will starts to use the ideas in their own programs so that their programs will work with the standard library more harmoniously.

As I explained in one of my earlier posts, I have a first-hand experience in the last point. To summarize, I started to write a function with an array in mind, but I happened to end up with writing a function that works with any “indexables”. In the process, I asked questions in this forum, but not all people there were aware of these “interfaces” and recommended array-specific solutions.

This is a huge waste of resources. All julia programmers should know that the standard library is written around these “interfaces” and when you write your own function, you should ask yourself “Does this argument has to be an array? Should I use contiguous integers starting from 1 to iterate over it?”

> [@](#):
>
> I think that small, piecemeal changes will be received better than large conceptual reorganizations.

I agree. I’ll think about how to proceed.

---

<div class="post-metadata">

**Author:** ![abraemer](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/abraemer/32/51403_2.png) [@abraemer](https://discourse.julialang.org/u/abraemer)\
**Post date:** [August 29, 2023, 8:09am UTC](https://discourse.julialang.org/t/the-challenges-of-documenting-generic-functions/103198/24 "2023-08-29T08:09:11Z")

</div>

I think you misunderstood. @Imiq talked about the functionality of having an “extended help section”. This has nothing to do with which method is actually documented. You can document each method of your liking with it’s own string which might contain “extended help”.

> **Code Example**
>
> ```julia
> """
> function f
> generic help for f
> # Extended help
> extended help for f
> """
> function f end
> 
> """
> function f(x)
> specific help for f(Any)
> # Extended help
> extended help for f(Any)
> """
> function f(x) return x end
> 
> """
> function f(x::Int)
> specific help for f(Int)
> # Extended help
> extended help for f(Int)
> """
> function f(x::Int) return 2x end
> 
> ```

This will show up as:

```julia
help?> f
search: f fd for fma fld fld1 fill fdio frexp foldr foldl flush floor float

  function f normal help - generic function
────────────────────────────────────────────────────────────────────────────
  function f(x) specific help for f(Any)
────────────────────────────────────────────────────────────────────────────
  function f(x::Int) specific help for f(Int)
────────────────────────────────────────────────────────────────────────────
Extended help is available with `??`

help> ?f
search: f fd for fma fld fld1 fill fdio frexp foldr foldl flush floor float

  function f normal help - generic function
  Extended help
  ≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡
  more info - generic function
────────────────────────────────────────────────────────────────────────────
  function f(x) specific help for f(Any)
  Extended help
  ≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡
  extended help for f(Any)
────────────────────────────────────────────────────────────────────────────
  function f(x::Int) specific help for f(Int)
  Extended help
  ≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡
  extended help for f(Int)

```

Also this has not really to do with type instability. If the compiler can infer the correct method to call and it’s output type, that’s stable. There is no need to have the same return type across all possible functions. In fact `f(x) = x` is perfectly type-stable for all arguments 🙂

---

<div class="post-metadata">

**Author:** ![fph](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/fph/32/17159_2.png) [@fph](https://discourse.julialang.org/u/fph)\
**Post date:** [August 29, 2023, 8:28am UTC](https://discourse.julialang.org/t/the-challenges-of-documenting-generic-functions/103198/25 "2023-08-29T08:28:22Z")

</div>

> [@abraemer](#):
>
> I think you misunderstood. @Imiq talked about the functionality of having an “extended help section”. This has nothing to do with which method is actually documented.

Thanks for the explanation, it’s clear now!

[Previous page](https://discourse.julialang.org/t/the-challenges-of-documenting-generic-functions/103198.md?page=1)
