
Oops, I mistakenly responded to a private copy of Henrik's
message and erased the public one. Resending to the
list. Sorry Henrik, but you started all of this. :-)
---------- Forwarded message ----------
Date: Thu, 8 Feb 2001 18:10:26 -0500 (EST)
From: Jan Skibinski
Jan, one question: what do you do/intend to do with *re*exported entities?
As explained in my previous mail, I think external documentation should include everything a module exports, including the related documentation, regardless of where the various entities were originally defined.
I agree. This is what is called a "flat interface" in Eiffel, which can be selectively made a bit bigger or a bit smaller. They have a "mother of all classes" called ANY (if I remember it correctly) which just brings too much noise in sometimes. So they turn if off. Something similar to our Prelude. But I am not ready for this yet.
I have to say that this already looks like a quite useful tool, and it does show that one can go a long way with very lightweight conventions. A few points, tough.
I'd again like to take the opportunity to push for the idea of also defining and intermediate format. The documentation samples Jan have presented are all very good examples of the kind of documentation renderings one might want. But on the other hand, I don't think they cover the entire spectrum of reasonable presentations. (I believe I have some support from at least Jan on this one.)
Definitely.
This brings me my main concern: is the *style* of conventions Jan proposes (not necessarily exactly those conventions he currently use) flexible enough to:
1. support other reasonable renderings, 2. avoid creating a feeling among users that the conventions are "dictatorial" ;-)
Regarding 2, I'm not entirely serious: by necessity, the conventions must be fairly strict. But after browsing through the Eiffel documentation Jan sent a pointer too, I personally felt that the required conventions were a bit too much. Now, I certainly do not wish to start a discussion about the Eiffel conventions. I'm just mildly concerned that too strict requirements might get in the way of getting wide acceptance for a standard. But maybe this is a non-issue.
The style I've shown is just a recommendation, not necesserily a requirement. You can write what you wish - a parser would not care less. I just found this kind of style tremendously readable. So take the "dictatorial" back, will you? :-)
Regarding 1, below are a few examples of things that I think are reasonable.
Please keep in mind that I too favour a fairly lightweight convention, but I am willing to allow a little extra noise for the sake of flexibility. To be concrete, I like the convention 'xxx' to mark a piece of code (such as a variable name) in running text which Jan proposes, I think one or two more such conventions would be useful (e.g. _xxx_ for emphasis). On the other hand, I don't necessarily see anything wrong with HDoc/JavaDoc-style tags for marking large things: the extra piece of information provided could be quite valuable.
This markup is invented for better readability but it would not be absolutely required. A properly structured comment should stand on its own legs - without any help from formatting. As an example - any of the following excerpts will do the same job: 1-- ...from 'module' 2-- ...from module 'm' 3-- ...from module m Versions 1 and 2 are just easier to read when rendered. Now to your challenges:
----------------------------------------------------------------------- Example 1.
I sometimes write functions which take tuples among their arguments and/or return tuples, and I sometimes find it useful to document each field separately.
Returning a tuple immediately implies that it might be difficult to start each documentation block with a sentence that describes what the function returns (which seems to be your convention)?
We have a beautiful keyword "where", which is perfect for such occassions. But I do not claim that writing good comments is an easy task. It is often a challenge. But think about it a bit.. Java style is just an easy way out: one writes the comments automaticaly, without even thinking about the future users. In contrary, when one has to structure the comment in most readable way one often finds a flow in ones solution. This is what happens to me sometimes... I am not up to your challenge in your example 1, since I do not fully understand its functionality. However, it could start the comment with something like this: -- Five-tuple (#1, #2, #3, #4, #5) of "whatever is -- your indented meaning of this tuple" ... blah -- where -- #1 - list of new top-level definitions [.. this and similar version example #1 cut out ..]
------------------------------------------------------------------------ Example 2:
The lambda lifter in the previous example illustrates another problem: how to deal with moands? NS happens to be a monad, so it is not really correct to claim that the function "returns a five tuple".
In Armin's HDoc, there is a separte tag for marking monadic return values. (But I think they still renders as "Returns ..."?)
In your case you seem to adopt the convention that functions with return type (IO a) should be described in imperative terms. This makes sense for IO and many other monads, but not necessarily for all monads.
Do we need more structure here, or are monads just such a general concept that there is not much one can do about it?
Good point. Who said that the allmighty "documentation commitee" is a bunch of lazy guys doing nothing? :-)
------------------------------------------------------------------------ Example 3:
This is really a variation on 2. Consider combinator libraries. Sometimes it makes sense to adopt special commenting conventions.
I agree here.
Again, the Fudget GUI combinator library can serve as a useful example.
The central abstraction in the Fudget GUI is the Fudget, which can be understood as a component with one user-visible input and one user-visible output. Such a component may or may not have a graphical rendering in the form of some GUI widget. Each fudget also has an invisible, low-level input/output pair which connects it to the outside world. An example could be a text input field. On the input it would accept strings which are shown as default values to the user. On the output, a user-entered string would appear as soon as the user presses return.
The documentation for a function like
foo :: a -> b -> F c d
where (F c d) is a fudget with input of type d(!) and output of type c, would be something along the following lines:
DESCRIPTION A foo fudget is a button that ... INPUT: True or False to switch the button on or off under program control. OUTPUT: True when the button is on, False when the button is off. ARGUMENTS: xxx :: a, ... yyy :: b, ...
The point here is that describing foo as a function returning a Fudget isn't very helpful. Instead special conventions approporiate for the domainin question were adopted.
Even if I agree that special conventions must be adopted sometimes, I could still attempt to raise to your challenge here :-) foo :: a -> b -> F c d foo xxx yyy -- Button fudget (obtained as a result of unknown -- to me foo operation on arguments 'xxx' and 'yyy'), -- whose i/o are: -- input - a program controlled boolean -- output - True if button is on (false otherwise, which is obvious and redundant) -- Assumption here is that user already knows all about the operational model Fudgets use. The low level documentation should not even attempt to solve ontological problems. If you write a vehicle user manual you may - at one point - safely assume that user knows what a clutch is. It's good if a single function is as self-contained as possible. Think for example about reading it in Haskell Module Browser. But sometimes nothing one can do without referring to a bit broader concept, such as a module or a library of modules.
I'm currently involved in the development of a framework for domain-specific languages called FRP (Functional Reactive Programming). One of its incarnations is as a combinator library. A central abstraction is (Behavior a b) which represents a "transformer" of signals of type a to signals of type b. I.e. there are some similarities to a fudget (F b a). Again, when we document a behaviour, it would be nice tobe able to talk about its inputs and outputs (which furthermore often happen to carry elements of tuple types).
So, can we find conventions which are flexible enough to support documentation of this type of code?
I still believe we can. I went through the Hawk exercises once to document them in this style and I was quite happy with the results. But I do not see anything wrong with customary styles for special cases - providing that user is given a chance to grab the top ideas first.
BTW, the Fudget library manual is available on line. It might be worth checking it out. For example:
http://www.cs.chalmers.se/Cs/Research/Functional/Fudgets/Manual/current/smal...
A concrete example illustrating the points above is:
http://www.cs.chalmers.se/Cs/Research/Functional/Fudgets/Manual/current/togg...
I am familiar with the concepts but I never looked at Fudgets from documentation point of view.
----------------------------------------------------------------------- Example 4
Well, not an example actually, more of a "laundry list". I touched on most of thses in my previous mail:
* A possibility to include pictures does not seem entirely unreasonable. As an extra, why not? * A convenient way of including a piece of code, e.g. a useage example. <code> </code> tags? * Explicit cross references Cf. the man-page "see also" style. Quite useful to be able to refer the reader to closely related functions in a large library, for instance. * Hints for generating indices at various level of detail (beginner's index, programmer's index, ...)
Many of the cross references, indices, etc. can be captured from the module structure itself. If I capture all structures of interacting modules, as Extractor intends to do, then I could - in principle - generate a lot of references, couldn't I? But yes, there are always special cases to consider.. Regards, Jan
participants (1)
-
Jan Skibinski