Introduction
In computer hardware architecture, the principle of Locality of Reference (attributed to Peter Denning) is that the processor tends to access the same memory locations, and others nearby, repeatedly over any given period of time. In an article revisiting the discovery of this principle, Peter Denning wrote [Denning 2006],
The locality principle flows from human cognitive and coordinative behavior. The mind focuses on a small part of the sensory field and can work most quickly on the objects of its attention. People gather the most useful objects close around them to minimize the time and work of using them. These behaviors are transferred into the computational systems we design.
The locality principle will be useful wherever there is an advantage in reducing the apparent distance from a process to the objects it accesses
This paper explores an application of the principle of Locality of Reference to computer programs and scripts, and in particular to XSLT templates and functions. It discusses some ways this principle has been applied with various degrees of success in software engineering; the paper then describes one particular application, that of generating both HTML and corresponding CSS in parallel using XSLT. After describing experience with this parallel generation the author will be in a position to describe why they consider it to be a success.
Locality of Reference in Software
An early problem in software, and one that continues to be a
problem today, is the task of ensuring that documentation for a
library is up to date with respect to the code. If you are using a
library of programming functions (for example, the EXPath File
module in XPath and XSLT), you rely on the documentation to tell you
what arguments you must supply to each function, to list the error
conditions, and to explain what the function returns. If the
documentation says, file:open
takes a
filename as its argument and returns a sequence of lines as
individual strings but in fact it takes a URI
Reference (informally, a URL) and returns a single, possibly empty,
string, your program may seem to be working correctly until you have
a Microsoft Windows filename with \ in it, or until you supply an
input file containing more than one line of text. The problem, then,
is this: How can such discrepancies between code and documentation
arise? And how can they be avoided?
In the early days of computing, program libraries were documented in printed books; the first of these was produced in 1951 in Cambridge Wilkes, Wheeler, Gill, 1951. This first book, like many after it, was typewritten, not prepared by computer. Later on, the Unix programmer’s manual was, unusually for the time, prepared on the same system it described: a PDP-11 computer running Unix. By the time the Seventh Edition of the manual was produced, it was a mixture of technical reports andman pages, with each library function having its own manual page, produced from a separate file using the troff typesetting software.
Producing the documentation for a library separately from the code implementing the library meant there was a duplication of information: the function signatures, listing the function names, parameters, and return types, were kept both in the software itself and in the external documentation. This created the possibility that the documentation and code could differ.
Literate Programming
In the 1970s and early 1980s the mathematician and computer scientist Donald Knuth saw this problem and designed a system in which the program and its documentation, both internal and external, could be interwoven. In effect the programmer was expected to write a text-book or extended essay about a problem being addressed by software, and to incorporate the text of the program into that work.
It may be useful to bear in mind that a great many people (although not all) have gone into computer science having barely ever written an essay, and certainly not enjoying the process. The author of this paper had to write exactly one essay as a computer science undergraduate, and it was for an elective course outside the computer science department. Turning the problem of writing a code library and some documentation into the task of writing a book is not universally seen as a simplification, nor as an inviting change, by such programmers. Perhaps this is part of why Dr. Knuth’s literate programming has not caught on en masse.
In the case that the requirements for a program seem stable, however, and the program will change only slowly over a long time (decades, perhaps), Knuth’s literate programming is an unparalleled tour de force.
A more serious problem with literate programming is that the methodology assumes a software life-cycle in which programs are designed and then remain largely static: they do not undergo significant reorganization. After all, if writing an essay is unappealing, rewriting the essay must be even less appealing. Since the program is interleaved with the documentation, refactoring means reworking the documentation even before the software design has become stable again. But any barrier to refactoring, however small, may lead to programs being rewritten from scratch, with new sets of bugs, rather than being reorganized.
Embedded Documentation
While Knuth was building complex cathedrals, others were kneeling in animal-hides and worshipping at hedge-altars. The author of this paper devised a system in the 1980s for personal use in the C programming language in which each function was preceded by a fragment of SGML describing it, itself contained in a comment so that the library would compile:
The approach of embedding the documentation in the program seems a much better fit with the relationship between a programmer and extended written prose than the reverse, embedding the program in the documentation. More importantly, where literate programming seemingly throws up barriers to refactoring and reorganizing code, embedded documentation does not. It is no surprise that similar systems are now widespread, from systems like doxygen for C or C++ to javadoc for Java.
Note that the early documentation method shown here mentions other functions by name, but there was no automated check that they had not been renamed.
Consider a programmer who, at some late hour, discovers the source of a bug. They make a correction to the code; they recompile, they run tests; they smile; they go to sleep. But in examining the code they did not need to look outside the function body they were repairing. As a result, it’s easy for necessary changes to the documentation to be overlooked. This is sure to be a factor why in JavaDoc, doxygen and other documentation systems (as well as the SGML-based system shown above) the documentation does often stray from the code. However, this style of documentation considerably reduces the problems of entirely separate program documentation, such as Unix manual page, that might go for decades and many major software revisions of the program described, without being updated.
Docstrings
The maintainers of the Python language were able to build on the work of others; both on systems such as doxygen or javadoc and on a much simpler system in some versions of the emacs editor. In this latter system, if the first item in a function body was a literal string it was taken to be a short (one-line) description of the purpose of the function.
Python uses a similar method with its docstrings: a single string placed after the start of the function serves as minimal documentation:
def schema_validate(xml, xsd): """Perform W3C XML Schema validation""" print("Validation failed: duplicate element found.")
Notice how the documentation, although much less complete in this example, appears after the start of the function. Since anyone working on a function is very likely to need to look at the function signature and parameter names, they are going to be reminded to update the documentation. It is this reminder that gives a clear example of the principle of locality of reference: because the documentation is in view of the programmer changing the code, it is easy to keep up to date. Such a simple change turns out to make a large difference in practice Unsub, 2021.
It should be noted that Python docstrings can be many lines long and for a class are expected to document all public methods.
Sad and Dismal Failures
Project failures have been attributed to programmers assuming they understood what a function did when it had perhaps a misleading name. This should, perhaps, be no surprise, if people become programmers because they dislike menial repetitive tasks and want the computers to do them instead.
If the principle of locality of reference says that we tend to
look nearby for things we need, it follows that we should write code
that can be understood as much as possible without having to look
elsewhere. A well-known source of software defect comes from calling
a function incorrectly, for example with an argument expressed in
feet instead of metres. Another example includes languages such as
Pascal and C++ in which function parameters can be passed implicitly
by reference, so that f(x)
can result in a change to
the value of a local variable x
even where
x
is not a pointer or reference.
Early programs had to use short identifiers because of memory
limitations. C programs, for example, could use variables of any
reasonable length but only the first six characters were significant
for global symbols shared between files. This is why Unix used
creat()
and mknod()
(the loader
prepends an underscore to globals, using all six characters). This
gave rise to a culture of using short variable names and function
names. The author of this paper was astonished to encounter, in the
1980s, a program with function names such as
addToTableOfContents(item, pageNumber)
but then saw
the advantage: you could read code that called
addToTableOfContents
without having to look at its
definition to guess what it did. The mixed case function name would
be treated as AddToT
on systems that still had the
six-character limit, a prefix slightly more likely to be unique than
add_to.
This property of being able to read a fragment of a program and understand it without needing to read the definitions of all the functions that it calls is another example of the principle of locality of reference. That is, where the previous examples have featured parallel information such as documentation that must be updated at the same time as code, this example features names that we must understand, ideally without having to leave the neighbourhood.
CSS Within
This section introduces a method of using CSS that is informed by the principle of locality. One use of XSLT is to transform a document represented in XML into two groups of files: one group, in HTML, intended as inputs to a Web browser or to a formatter to make PDF; the other group, consisting of images, CSS and JavaScript, to be referenced by the HTML files in the first group.
A problem arises that is analogous to that of software documentation: the CSS and JavaScript must be kept up to date with any changes in the HTML structure, and changes to the HTML structure may necessitate in turn changes to the CSS.
It might seem that this should be trivial to manage, but a CSS file as short as only six or seven thousand lines is already larger than the Version Six Unix kernel source. Worse, the cascading nature of CSS means that multiple CSS rules might apply to any given element, and might appear anywhere in the CSS stylesheet.
CSS Within is an attempt to apply the principle of locality of reference to the problem of keeping CSS and HTML and XST all synchronized.
CSS Four Ways
When the author of this paper was first faced with the problem of generating a static HTML Web site with CSS styling, they simply made an external CSS file. Unfortunately as the XSLT was modified independently of the CSS, the CSS gradually grew longer and is no longer feasible to maintain at all.
The next approach was to generate a CSS file from within a
single XSLT make-css
template. This at least meant
that when editing a template, the corresponding CSS selector
could often be found quickly. It was an improvement but not a
solution, though ,as it was easy to forget to update one or
another. Removing an element constructor in CSS might or might
not remove the need for a particular group of CSS style rules –
and those rules might or might not be near one another in the
CSS, again violating our locality of reference principle.
The second approach was to use non-XSLT elements. It turns
out, as many readers will already know, that you can include
elements from non-XSL namespaces at the top level in XSLT
stylesheets. So it was possible to have, for example, a
css:styles
element just before each template.
In practice there were some difficulties with doing this. The
first was remembering to look before the start of the template.
Another difficulty (shared with other approaches already
mentioned) was that curly braces in text nodes have become
special in XSLT 3: if the expand-text attribute is set to
yes on the stylesheet element, then you
need to turn it off again for each such CSS element so the curly
braces do not introduce embedded XPath expressions. A third
difficulty was that tie granularity did not
match the problem: CSS styles are applied to individual elements
in their context, but an XSLT template might generate many
different elements.
Applying the principle that we need to have everything relevant to hand, then, CSS Within was born. Consider the following fragment taken from inside a template in a production XSLT stylesheet:
<xsl:template name="make-breadcrumb-links"> <div class="index" role="navigation"> <css:rule match="div.index"> padding: 1rem; margin: 0; max-width: 20rem; </css:rule> <ul class="breadcrumb"> <css:rule match="ul.breadcrumb"> list-style: none; /* turn off the bullets */ </css:rule> . . . </ul> </xsl:template>
In the listing, the direct element constructor creating the HTML div element is immediately followed by a CSS fragment to match it. There could be multiple CSS rule elements as needed. The generated CSS would look like this:
div.index { padding: 1rem; margin: 0; max-width: 20rem; } ul.breadcrumb { list-style: none; /* turn off the bullets */ }
In the example, the HTML div
element and the HTML
ul
element each have their own separate styles,
directly associated with them. This has resolved or at least
greatly reduced the problem of granularity. Since the CSS is now
embedded within the direct element constructor, rather than
separated from it and outside the template, this has also
resolved the difficulty of the person maintaining the XSLT
having two places to update in parallel. Finally, moving the
selector into an attribute means that curly braces are not
needed, and now the CSS syntax can happily co-exist with XSLT
3.
This approach needs more support than simply putting the CSS before the template. The css:rule elements are considered by an XSLT processor to be “direct element constructors”, so they and their contents appear in the output. To deal with this, the author has used two different approaches. The first, shown in the appendix to this paper, is to use the XPath fn:transform() function to apply a stylesheet and then remove extraneous CSS elements before creating the final output.
It may seem that the CSS could be bundled up and written to
the CSS file, perhaps with an XSLT 3 accumulator, as the input
is processed, but in fact what is needed is
all of the CSS elements, including ones
not triggered by templates, for example for server-generated
dynamic content or for static HTML pages sharing the same CSS
stylesheet. Therefore, the XSLT separately processes the XSLT
stylesheet as XML, gathers the css:rule
elements,
and writes the stylesheet.
The author has also written very simple a Java extension class for Saxon so that the CSS elements do not generate any content; this is available (both source and compiled) on the gitlab page for CSS Within.
Putting the CSS inside XSLT element constructors in templates has the effect of interleaving the XSLT source and the CSS source. Evaluating the XSLT entails separating out the two streams. The CSS is removed when the XSLT stylesheet is compiled (either by XSLT pre-processing of the stylesheet itself, or using a Java implementation to do this). Since the CSS is no longer present when the XSLT is evaluated, property values cannot refer directly to XSLT variables; a mechanism to include dynamically-generated content in the CSS sylesheet is described in the next section.
CSS Within in More Detail
This paper does not attempt a complete definition of CSS Within, but illustrates enough of it for the purpose of discussing the application of the principle of locality of reference to software maintenance. The full documentation is available on the gitlab page for CSS Within.
|
This element has a match attribute, and generates a single CSS rule. The content should be CSS properties. It’s also possible to reuse fragments of CSS with
a ref attribute to point to a
A <!ELEMENT css:rule (#PCDATA)*> <!ATTLIST css:rule match CDATA #IMPLIED stream CDATA #IMPLIED name ID #IMPLIED ref ID #IMPLIED > |
|
This element models CSS media queries (specific in
the W3C CSS Conditional Text module). It contains
any mix of <!ELEMENT css:media (css:rule|css:media)*> <!ATTLIST media-query when#CDATA #IMPLIED stream CDATA #IMPLIED > For example, the following input: <div class="navbar"> <css:rule match="div.navbar"> font-size: 80%; </css:rule> <css:media when="max-width: 600px"> <css:rule match="div.navbar a"> display: inline-block; min-height: 48px; min-width: 48px; </css:rule> </css:media> <xsl:apply-templates /> </div> produces the following CSS result: div.navbar { font-size: 80%; } @media (max-width: 600px) { div.navbar a { display: inline-block; min-height: 48px; min-width: 48px; } } The effect of the media query is that if the
viewport (the screen or page) is less than six
hundred pixels wide, |
There are also constructs for at-rules, a CSS header and footer, and ways to get at the generated stylesheet.
In all cases the curly braces are generated automatically, and the CSS rules can be placed near the code generating the elements to which they will apply, or, as in the media query example, in the parent element's XSLT template.
Writing Out CSS Styles
Regardless of how many times any particular XSLT
template was used in a transformation, the CSS stylesheet
contains each css:rule
element exactly once.
The rules appear in the order in which they occur in the
stylesheet.
If you need to put rules in a different order, you can put
them between templates or in a template not otherwise used,
and give them names; then refer to them with name/ref pairs
from empty css:rule
elements where they are
needed, to remind your later self, and others, where they
apply.
The stylesheet is constructed as a string; it is possible
to call fn:replace()
on it from within XSLT
before writing it out. In addition, you can make a header
that defines CSS custom properties (CSS variables) and refer
to them in the stylesheet.
The implementation of CSS Within currently on gitlab uses
fn:transform()
to run a modified version of
the stylesheet with the CSS rules removed, or removes any
errant CSS instructions from the output; it then uses a
namespaced XSLT mode to gather up the CSS rules and write
them out. Some cleverness, described in an appendix to this
paper, would be needed to do this in the case that there are
multiple stylesheet compilation units (possibly including
external precompiled packages) that might be selected at
runtime.
Alternate Designs
It's very tempting to want to make the CSS properties be XML attributes instead of text content. There are some problems with this, however.
-
The attributes must be processed without evaluating the stylesheet. XSLT developers are accustomed to thinking of attributes as first-class objects, passing them around, generating them in functions, using dynamic attribute sets, using attribute value templates to interpolate runtime values, and more. None of these techniques work when the XSLT stylesheet is treated as a passive XML document containing CSS fragments.
-
It often happens that a CSS property must be repeated in the same rule with different values: different user agents (browsers) will use whichever value they consider valid and reject the others. You cannot have two XML attributes with the same name, so this rules out using the obvious attribute-name/value approach.
-
Some CSS property values do contain curly braces, but there's no equivalent to
expand-text = "no"
for attribute values, so you are back to difficulties with curly braces, compounded by the fact that you can't use a runtime variable. -
Although the forgoing reasons are surmountable with varying degrees of inconvenience, a far greater problem is the distance between XSLT and CSS cognitive modes for the human reader. It's much easier to read a CSS example in CSS syntax and compare it to online examples, or to copy and paste to and from a Web browser element inspector. The way CSS is written is part of the way people think about CSS, so it's important to support keeping it that way.
In particular, the CSS cascade works very differently from XSLT template priorities. In XSLT, an entire template is selected by the processor based on priorities. In CSS individual rule/value pairs are selected, and in some cases merged, based on a mixture of ordering in the input file and how specific the selectors on the CSS rule surrounding them are. It’s easy to forget this and to imagine that an entire rule (between open and close curly braces) is to be selected; getting this wrong can lead to white text on a white background, or other styling errors.
None the less, the author is considering using an
attribute-based approach to font references, so some
experimentation is happening and CSS Within may evolve
towards supporting a richer markup for individual CSS
property-value pairs in the future, as well as for at-rules
such as @font-face
or @page
which
at the moment must be supplied separately, for example in a
header included when the CSS is written.
Future Work
CSS Within continues to evolve through experience and
contemplation. A current experiment makes the match
attribute optional on css:rule
elements,:
instead, the immediately enclosing direct element
constructor is examined. This makes it easier to rename
elements or classes, and easier to copy style blocks. The
example from earlier in this paper, showing the use of a
media query, might become:
<div class="navbar"> <css:rule > font-size: 80%; </css:rule> <css:media when="max-width: 600px"> <css:rule match="div.navbar a"> display: inline-block; min-height: 48px; mon-width: 48px; </css:rule> </css:media> <xsl:apply-templates /> </div>
Only the second line of the example is changed; in
practice, however, this change would likely simplify almost
all css:rule
elements. The question to be
determined is whether the change increases or reduces
maintainability.
More support for CSS at-rules is planned, for example for
fonts or keyframes; experiments using an attribute on a
css:rule
element to point to an at-rule for
a @font-face
have not been promising so far, as
the added complexity gave minimal benefit. However, hooking
into infrastructure to test that font files are in place may
give added motivation. In addition, automatically generating
the latest version of the “bullet-proof Web font” syntax
from something simpler would be a benefit. The following
listing gives an example of a CSS font
definition:
@font-face { font-family: "IM Fell English PRO"; font-slant: normal; font-weight: regular; src: url('fonts/imfellenglishpro.eot'); src: url('fonts/imfellenglishpro.eot?#iefix') format('embedded-opentype'), url('fonts/imfellenglishpro.woff2') format('woff2'), url('fonts/imfellenglishpro.woff') format('woff'), url('fonts/imfellenglishpro.ttf') format('truetype'); /* SCG fonts via CSS are deprecated now, see * https://www.zachleat.com/web/retire-bulletproof-syntax/ * url('fonts/imfellenglishpro.svg#imfellenglishpro') format('svg'); */ }Notice especially the tricks such as
?#iefix
used if Internet Explorer support
is desired, along with the need to repeat the first
src
property-value pair. Complexities such
as this, along with the occasional need for actual syntax
errors to support incorrect implementations, makes a
markup-based representation especially complex. Simple
attribute-value pairs do not work because of the repetition.
However, simply surrounding the rule with element and using
name/ref for validation may be useful in
itself:
<cs:font-face name="imfelleiglishpro"> font-family: "IM Fell English PRO"; font-slant: normal; font-weight: regular; src: url('fonts/imfellenglishpro.eot'); src: url('fonts/imfellenglishpro.eot?#iefix') format('embedded-opentype'), url('fonts/imfellenglishpro.woff2') format('woff2'), url('fonts/imfellenglishpro.woff') format('woff'), url('fonts/imfellenglishpro.ttf') format('truetype'); /* SCG fonts via CSS are deprecated now, see * https://www.zachleat.com/web/retire-bulletproof-syntax/ * url('fonts/imfellenglishpro.svg#imfellenglishpro') format('svg'); */ </css:font-face>With this simple change, the font-face CSS rule could be included only if needed, and a warning generated on an attempt to use a font-face by reference that was not defined.
For Web use it’s important to include font definitions as
early in a stylesheet as possible, so that the browser can
start the process of loading the font. CSS is generated by
the CSS Within XSLT stylesheet in the order it occurs in
the input XSLT you are using, so you can have an
otherwise-unmatched template at the start of your
stylesheet, or an xsl:variable
definition,
containing rules to go at the start.
There is also ongoing work with extension elements. The
Java class for Saxon that makes css:rule
and
css:media
return an empty sequence at
runtime could also help to write out stylesheets, but the
author ran into a combination of time constraints and
unclear documentation, so this is not yet an active part of
the CSS Within distribution.
CSS Within can also be used with systems such as the SASS preprocessor, although some of the SASS benefits, such as nesting, are irrelevant since CSS Within uses the natural nesting of direct element constructors.
CSS Within In Practice; An Unwarranted Conclusion
It took the author an hour or two to convert one standalone CSS file of some 6,500 lines to CSS fragments within an XSLT stylesheet. However, the time has paid for itself in unexpected ways. Not only are the styles now always up to date, but the act of finding the particular style rule has become trivial, which has saved far more time than anticipated.
It is difficult to contemplate going back to keeping CSS in a separate file. The necessity of handling extension elements, or of post-processing the XSLT result, is unfortunate. Preprocessing the XSLT to remove CSS elements before evaluation sounds tempting, but in XSLT 3 stylesheet filenames for inclusion could be supplied as parameters and package selection can depend on system properties or even environment variables, so this is not in general possible.
Some months after implementing CSS Within, the author had occasion to return to the original project. They found that they were easily able to modify and refactor the stylesheet as needed, updating the styles. Previously, returning to the project after some time has always proved difficult.
Moving a dependent resource into the centre of the code, instead of cluttering the code, provides an overall clarity and increase in efficiency. Furthermore, there is a reduced impediment to refactoring compared to an external stylesheet, because the effects of making changes are more readily apparent.
In fairness, one should contrast the possibility, literate-programming style, of embedding XSLT inside CSS stylesheets. However, not only would this discourage refactoring, as already suggested, but it would bring back the difficulties of curly braces, and would add the same impediment to updating: that it would be easiest to modify a template without looking at the corresponding CSS. With CSS Within it is easier to look at both CSS and XSLT than to look at only one, because the CSS is within the XSLT at the point where it is needed, and yet kept subsidiary. Making it easier to do the right thing than the wrong thing leads to an overall improvement in code as well as in quality of life.
The Principle of Locality of Reference is useful in leading us to ways of writing code that is more readable, more reliable, and much easier to maintain.
Appendix A. Implementing “CSS Within” With XSLT
There are three parts to the implementation:
-
Checking the CSS elements are used correctly, with for example no
css:media
elements insidecss:rule
elements; -
Handling the unwanted constructed CSS nodes when the stylesheet is executed;
-
Generating the CSS stylesheet.
In the current implementations, the first item, that of validation, is handled by XSLT that also removes unwanted nodes.
The second item, that of removing the unwanted nodes, as achieved as follows: either with a Java extension element that returns the empty sequence on compilation, so that the nodes are not generated, or using fn:transform()to call XSLT and then post-processing the result with an identity transform that removes all elements in the CSS Within namespace. It is also possible to pre-process the stylesheet to remove the CSS direct element constructors (and their contents) and then use fn:transform() on the result. However, this does not take external packages into account.
Generating the stylesheet is done currently by processing the
stylesheet with XSLT; the author also had extensions written in Java
to provide a css:get-stream() function so that
the stylesheets could be written from the XSLT stylesheet but this
did not work with separate compilation of packages, nor with
multiple stylesheet files. A newer approach was started: this would
augment a css:gather
element in each file or
compilation unit with the generated text of the style sheet, so that
it can be placed in a template that uses xsl:next-match
to process all of the stylesheet files at runtime.
An XSLT variable can be define to hold a CSS header containing an
encoding declaration, initial comments, @font-face
,
@page
and other at-rules, and this can easily be
prepended to the CSS file when it is created from XSLT. Such a
header can also define custom properties (CSS variables) which can
then be referenced from property values in css:rule
elements. This considerably reduces any need to construct XSS
property values at runtime inside actual templates, which is just as
well since the CSS is gathered before the stylesheets are even
execute!.
Appendix B. A Slightly Longer Example
The following is a complete template from a production stylesheet.
<xsl:template name="make-navbar"> <xsl:param name="relative-path-to-letters" select="string('../')" /> <xsl:param name="node" select="$doc" as="document-node()" /> <p class="navbar"> <css:rule match="p.navbar"> font-size: 80%; text-align: center; margin-top: 0.5em; margin-bottom: 0.5em; border-top: 1px dotted; border-bottom: 1px dotted; </css:rule> <xsl:for-each select="distinct-values($node/dictionary/letter/@lc)"> <xsl:text> </xsl:text> <a href="{$relative-path-to-letters}{.}/"> <css:rule match="p.navbar a"> text-decoration: none; </css:rule> <!--* for touch devices: *--> <css:media when="max-width: 600px"> <css:rule match="p.navbar a"> display: inline-block; min-height: 48px; min-width: 48px; </css:rule> </css:media> <xsl:value-of select="upper-case(.)"/> </a> <xsl:text> </xsl:text> </xsl:for-each> </p> </xsl:template>
References
[Denning, 2005] Denning, Peter J., The Locality Principle, in Communications of the ACM, Vol 48, No. 7, July 2005. doi:https://doi.org/10.1145/1070838.1070856.
[Unsub, 2021] Unsubstantiated assertion provided without evidence.
[Wilkes, Wheeler, Gill, 1951] Wilkes, N., Wheeler, D., Gill, S., Report on the Preparation of Programmes for the EDSAC and the Use of the Library of Subroutines, University Mathematical Laboratory, Cambridge, 1951.