Should we be documenting the type that a function returns?

I’ve been studying the Image.jl package and I’ve noticed that whilst the documentation for a function explains what each parameter does, the documentation in general does not comment on the data structure that the function returns.

For example, say I want to find the corners in an image , without actually looking at the source code of the function, I don’t know whether the corners will be a returned as a matrix of numbers, or a vector of special corner types, or a matrix of Boolean etc.

I’m wondering if this is idiomatic of Julia packages in general? Is there a particular reason why return types are not discussed, or is it just a convention adopted by that particular package (@tim.holy )?

I can’t speak for other people, but I like to organize my code around verbs (ie functions) instead of nouns (values and their types). So if I call

y = foo(x)

it is more important for me to know that what y represents and what I can do with it, eg

z = bar(y)

than how it is actually implemented. The former I can find out by

  1. looking at the library docs,
  2. using methodswith or similar.

For a well-designed library, the answers to these questions should be the same even if the type of y is changed at some point. If I am really curious about he latter, I can always do ? on the type of y, dump(y), etc. But I rarely feel I need to.

1 Like

There is no rule. I personally think that it is useful and so do the authors of Base (there is also some issue about the preferred syntax, but I cannot find it):

help?> length
search: length hooklength set_length! leglength pol_length

  length(A::AbstractArray) -> Integer

  Returns the number of elements in A.

It’s interesting and deliciously ironic that you found that in the Images package, because I’ve recently advocated a related viewpoint. I agree that we should be informative about the outputs, and when you find otherwise it’s most likely a chance for improvement.

That said, I’d echo @Tamas_Papp’s point above. With regards to input to a function, usually I prefer to design my code so that it only requires certain “behavioral contracts,” but these contracts don’t always require a specific representation: they might work for a tuple, Array, or other kind of iterable container. I’m not sure the outputs should be treated differently.

Certainly would be easier to do with some way of describing the return values as having a flavor of some sort…some sort of…trait? :wink:

…ok, I’ll be quiet now.