This is an elucidative program which illustrates the use of multiple source program versions. Notice that the documentation as such is not versioned. The reason is that the documentation is intended to be able to address the evolution of the software as such. Thus, the documentation transcends the versions of the programs. The demo is quite similar to the Demo Program which I wrote for the paper Scheme Program Documentation Tools.
For a larger and more realistic example please see the documentation of the Scheme Elucidator itself.
In this small elucidative program we will illustrate the versioning features of the Scheme Elucidator 2. In the documentation part we will draw the readers attention to the relevant features.
The original versions of prog1 and prog2 have been used in other demo programs. These are designated as version 1. You can see the version number in the upper right corner of the source program, as a water mark. The newest versions, prog1 and prog2 have been modified in various ways. The only aims of the modifications has been to illustrate the versioning features of the Scheme Elucidator 2. Let us already here notice that links to older versions are shown on a grey background.
We start the discussion of the function fac. In version 1 the fac function is recursive. In version 2, we have changed the fac function to be iterative. Hereby we have introduced the usual helping function fac-iter. You should notice the icon of fac . Also, you should notice that fac-iter is marked as . Also notice the possibility of navigation in between version 1 and version 2, by means of the grey arrows, such as , above the definitions in the source programs.
Version 1 of prog1 has two functions called head and tail. These functions have no counterpart in version 2. Thus, these two functions have been delete from the program. Notice the special 'dead end' icon (similar to the well-known road sign) used in version 1 to indicate that you cannot navigate to succeeding versions of these abstractions.
Recall that the Scheme Elucidator uses the icon in source programs to link to the place in the documentation, where a particular abstraction is discussed. It is possible to direct some documentation towards a specific version of the documentation. When this is done, the icon is used instead of . When we discussed head and tail above we explicitly referred to version 1. This explains the use of in the documentation. Thus, the use of tells the source program reader that there exists documentation that addresses the specific version of the source program.
Let us assume that we have written some documentation about prog2 some time ago. The documentation corresponds to version 1 of prog2. Now time passes, and prog2 is updated in various ways. We end up with prog2. As a typical scenario, however, the documentation of prog2 is not updated. Below we show some documentation taken from section 2.1 - 2.3 of Demo Program.
When we address an abstraction from the documentation, without explicit use of the version vers attribute, we attempt to identify the newest versions of the abstraction. If this cannot be done, we fall through the versions - from the newest (highest) towards the oldest (1). When reading the documentation below, you should observe this "version fall through" facility. Recall that links to older versions are shown on a grey background.
Italic portions of the text below are meta comments, intended to explain the versioning points. The non-italic parts of section 3.1, 3.2 and 3.3 have not been altered, in comparison with the original documentation.
From version 1 to version 2 we have moved the filter function from prog2 to prog1. Therefore both filter and filter-help are marked as moved, using the icon . A function marked as moved with this icon exists - structurally equal with the current definition - in another source file. The grey link icon, links to the function which has been moved. Notice that the original documentation - as can be seen in the following paragraph - is unaffected. The main reason is that filter and filter-help are addressed without mention of the source file to which they belong. Most often in the Scheme Elucidator, the documentation remains valid even if the program is reorganized.
The function filter makes use of the tail-recursive function, filter-help, which iteratively carries out the filtering. Due to use the iterative processing in filter-help, we need to reverse the result in filter, .
The function compose is renamed to compose-functions in the latest version of prog2. The renaming implies that the documentation links to the original version (version 1). The mutual navigability between compose and compose-functions is lost at the program side. The function compose-functions is seen as a new function.
The function zip-lists has also been renamed. The original name was just zip. In this case, the Elucidator is clever enough to identify the fact that zip has been renamed to zip-lists. This is signalled with the icon , and the arrow links to the 'old name version'.
Why could the Elucidator not find out that compose was renamed? Well - the only reason is that compose-functions is recursive, and therefore the body of compose-functions refers to its own name. Therefore the body of compose and compose-functions are not structurally equal!
Composition of two or more functions can be done by the function compose. The function handles two special cases first, namely the trivial composition of a single function , the typical composition of two functions , and composition of more than two functions .
The function generate-leq has been deleted in version 2. However, of some reason (most likely an oversight) its helping function list-index has survived. The documentation below is only relevant for version 1. As shown several times before, the link to generate-leq is greyed.
It is sometimes useful to be able to generate a 'less-than-or-equal' function from an explicitly given enumeration ordering. This is done by the function generate-leq and its helping function list-index. Values of the enumeration-order are supposed to occur as constituents of some data structure. The selector function selector accesses the enumeration values within the data structure. Enumeration values are compared using eq-eq?, which is an optional parameter of generate-leq . Notice the pattern used for handling of optional parameters, and in particular the use of the function optional-parameter.
In section 3 we have shown what happens if old documentation is attached to updated programs. When reading through section 3.1, 3.2 and 3.3 we easily realize that (at least) section 3.3 is outdated. It is possible to mark a documentation section or a documentation as outdated, by putting an explicit program-version number on it. Notice that this forces all links in this section to go to a particular version. Below we show this for section 3.3. To visually emphasize that section 4.1 is outdated, it can be arranged that the whole section is shown on a grey background. This is done by using the body attribute body-style. It is, as an alternative, possible reduce the text size of the body text.
It is some times useful to be able to generate a 'less-than-or-equal' function from an explicitly given enumeration ordering. This is done by the function generate-leq and its helping function list-index. Values of the enumeration-order are supposed to occur as constituents of some data structure. The selector function selector accesses the enumeration values within the data structure. Enumeration values are compared using eq-eq?, which is an optional parameter of generate-leq . Notice the pattern used for handling of optional parameters, and in particular the use of the function optional-parameter.
In section 3 we showed what can happen if we use the Scheme Elucidator with outdated documentation on updated programs.
In this section we will show how we can document the evolution of a program. Thus, here we rewrite the documentation of prog2 in order to reflect the changes in the software. The documentation primarily emphasizes the software evolution from version 1 to version 2 of prog2.
We should start noticing that the program we discuss in this demo is solely a collection of a few, largely unrelated functions.
The function fac has undergone a change from a recursive version to an interative version. Notice in this context that it is the helping function fac-iter that makes the real difference between the two.
Notice that we in a few paragraphs, and with use of precice references to old and new definitions, can carry out a discussion of the way the program has evolved. Notice also how the icons , , ,and help us understand the fine grained evolution of the program source files.
Even though the Scheme Elucidator is quite good at spotting new, updated, moved, or renamed definitions it is not yet perfect.
If a definition is moved from one source file to another, we can trace the moving from the target to the source, but not yet in the other direction.
A similar observation holds for renaming. Thus, we link from the new name definition to the old name definition (in a previous version of the same source file). But we are not yet able to trace the evolution from the old name version to the new name version.
The Elucidator uses some very strict predicates for comparison of definitions. Currently, we use Schemes equal? function. As we saw with compose and compose-functions it might be desirable to use a less strict function to determine if two definitions are considered as being equal. Maybe, differences in comments should not count. Maybe recursive calls should be 'name adjusted'. And maybe other minor differences be taken into account explicitly.