@SubSection @Tag { cross } @Title { The cross reference abstraction } @Begin @PP In developing the cross reference abstraction, it seemed best to begin with the database application, since it is the simplest. Database relations are naturally mapped into Lout definitions: @ID @OneRow @Code { "def @Reference" " named @Tag {}" " named @Author {}" " named @Title {}" " named @Journal {}" "{}" } The set of all invocations of @Code "@Reference" is a relation whose attributes are the parameters, and whose tuples are the invocations. To complete the correspondence, we need only declare that the @Code "@Tag" parameter is special, serving as the key attribute. @PP Following the database model, we next need a notation for retrieving the invocation with a given tag: @ID @Code "@Reference&&kingston91" This @I {cross reference} is like an arrow pointing to the invocation. To access its attributes, we write @ID @Code "@Reference&&kingston91 @Open { @Author, @Title }" The @Code "@Open" operator evaluates its right parameter in an environment which includes the exported parameters of its left. @PP An invocation is chosen to be a running header because of its proximity to the place where it is used, rather than by its tag. Such proximity is naturally expressed by two special tags, {@Code preceding} and {@Code following}; for example, @Code "@Sym&&following" will point to the closest following invocation of @Code "@Sym" in the final printed document. This is much simpler conceptually than reference to the internal state of the document formatter at a critical moment, the usual approach to running headers. @PP It turns out that the above design solves all the cross referencing problems encountered in practice except one, which may be typified by the problem of finding the number of the page on which the chapter whose tag is @Code "intro" begins. Two cross referencing steps are needed, first to {@Code "@Chapter&&intro"}, then from there to {@Code "@Page&&preceding"}, where the page number is known. @PP Given our success so far, this last problem proves to be surprisingly difficult. We first try @ID @OneRow @Code { "@Chapter&&intro @Open {" " @Page&&preceding @Open { @PageNum }" "}" } but this fails because @Code "@Page&&preceding" is evaluated in the present context, not in the context of @Code "@Chapter&&intro" as required. So our next attempt is @ID @OneRow @Code { "def @Chapter" " named @PageNum { @Page&&preceding @Open { @PageNum } }" " ..." } with the @Code "@Page&&preceding" cross reference attached to the chapter; we write @ID @Code "@Chapter&&intro @Open { @PageNum }" This also fails, because parameters are evaluated after substitution, so once again @Code "@Page&&preceding" is evaluated in the wrong context. We could of course define a new operator specifically for this case: @ID @Code "@Page&&{ @Preceding @Chapter&&intro }" or some such. This is free of the annoying context-sensitivity, but it seems quite complex, and the expected cross reference @Code "@Page&&preceding" does not appear. @PP The author was lost in these obscurities for some time, and ultimately rescued himself by looking ahead to the implementation of the @Code preceding and @Code following tags, to see if a simple extension of it would solve the problem. This led to the @Code "@Tagged" operator: @ID @Code "@Page&&preceding @Tagged intro" placed at the beginning of the body of the chapter will attach @Code intro as an extra tag to the closest preceding invocation of {@Code "@Page"}, so that @ID @Code "@Page&&intro @Open { @PageNum }" yields the desired page number. There is something low-level and ad hoc about the @Code "@Tagged" operator, but the two cross references do appear naturally, and it works. @End @SubSection