Designing Functions for Mutually-Referential Definitions

The recipe for designing functions on mutually referential data definitions generalizes that for self-referential data. Indeed, it offers only two pieces of additional advice. First, we must create <#18596#>several<#18596#> templates simultaneously, one for each data definition. Second, we must annotate templates with self-references and <#18597#>cross-references<#18597#>, that is, references among different templates. Here is a more detailed explanation of the differences:
The data analysis & design:
If a problem statement discusses several different kinds of compound information of arbitrary size, we need a group of data definitions that are self-referential and that refer to each other. We define such groups in one block. As usual, we identify the self-references, but we also identify the cross-references. In our example in the preceding section, the data definition consisted of two sub-definitions:

#picture18600#

The first one concerns <#18630#>parents<#18630#> and another one for <#18631#>list of children<#18631#>. The first (unconditionally) defines a parent in terms of symbols, numbers, and a list of children, that is, it contains a cross-reference to the second definition. This second definition is a conditional definition. Its first clause is simple; its second clause references both the definition for <#63810#><#18632#>parent<#18632#><#63810#>s and <#63811#><#18633#>list-of-children<#18633#><#63811#>.

Contract, Purpose, Header:
To process interrelated classes of data, we typically need as many functions as there are class definitions. Hence, we must formulate as many contracts, purpose statements, and headers in parallel as there are data definitions.

#tabular18635#

<#18675#>Figure: Designing programs for definitions with mutual references<#18675#>

<#18677#>The essential steps<#18677#>

<#63815#>(Refines the recipes in figures~#figdesign1#18678> (pg.~#figdesign1#18679>), #figdesign3#18680> (pg.~#figdesign3#18681>) #figdesign4#18682> (pg.~#figdesign4#18683>))<#63815#>


Templates:
The templates are created in parallel, following the advice concerning compound data, mixed data, and self-referential data. Finally, we must determine for each selector expression in each template whether it corresponds to a cross-reference to some definition. If so, we annotate it in the same way we annotate cross-references. Here are the templates for our running example:

#picture18684#

The <#63820#><#18749#>fun-for-parent<#18749#><#63820#> template is unconditional because the data definition for <#63821#><#18750#>parent<#18750#><#63821#>s does not contain any clauses. It does contain one cross-reference to the second template: to process the <#63822#><#18751#>children<#18751#><#63822#> field of a <#63823#><#18752#>parent<#18752#><#63823#> structure. By the same rules, <#63824#><#18753#>fun-for-loc<#18753#><#63824#> is conditional. The second <#63825#><#18754#>cond<#18754#><#63825#>-clause contains one self-reference, for the <#63826#><#18755#>rest<#18755#><#63826#> of the list, and one cross-reference for the <#63827#><#18756#>first<#18756#><#63827#> item of the list, which is a parent structure. A comparison of the data definitions and the templates shows how analogous the two are. To emphasize the similarity in self-references and cross-references, the data definitions and templates have been annotated with arrows. It is easy to see how corresponding arrows have the same origin and destination in the two pictures.

The body:
As we proceed to create the final definitions, we start with a template or a <#63828#><#18757#>cond<#18757#><#63828#>-clause that does not contain self-references to the template and cross-references to other templates. The results are typically easy to formulate for such templates or <#63829#><#18758#>cond<#18758#><#63829#>-clauses. The rest of this step proceeds as before. When we deal with other clauses or functions, we remind ourselves what each expression in the template computes, assuming that <#18759#>all<#18759#> functions already work as specified in the contracts. Then we decide how to combine these pieces of data into a final answer. As we do that, we must not forget the guidelines concerning the composition of complex functions (sections~#seccompounding1#18760> and~#seccompounding2#18761>).
Figure~#figdesign6#18763> summarizes these pieces of advice; it should be read in conjunction with figures~#figdesign1#18764>, #figdesign3#18765>, #figdesign4#18766>, and~#figdesign5#18767>.