For further information on Literate Programming:
Click here to view the Web page on literate programming.
[B86a] J. Bentley, "Programming Pearls: Literate Programming," CACM 29, No. 5, May 1986, pp. 364-369.
[B86b] J. Bentley, "Programming Pearls: A Literate Program", CACM 29, No. 6, June 1986, pp. 471-483.
[K] D. E. Knuth, "Literate Programming", The Computer Journal 27, No. 2, 1984, pp. 97-111.
[W] R. N. Williams, Funnelweb User's Manual, V1.0 for FunnelWeb 3.0, May 1992.
Core problem:
We write code for a computer, not a human reader!Donald Knuth observes:
Knuth invented literate programming.
"The literate programmer: [K, p. 97]
You should write a program from the start as a literate program. Do not in normal cases try to "retrofit" a program with English to form a literate program.
I personally believe that object oriented programming gives us a way to:
What's missing:
Way to understand program as whole (I see the individual trees, but what does the forest look like?)
sorted list of M random numbers in range 1..N in which no integer occurs more once
If M=5 and N=10, one possible output is: 1 5 6 8 9
In class we'll go over a literate program solution solution (pp. 366-367 in [B86a])
Example:
"The first order of business is to have a short dialog with the user."
Example:
Knuth refers to set S in #6 before explaining it in #7.
A big advantage of literate programs over plain source code is that you can include:
In class we'll go over a second literate program example [B86b] that illustrates procedures, gotos, and other things.
Given a text file and an integer k, "the most common words are to be printed in order of decreasing frequency, with words of equal frequency listed in alphabetic order. Printing should stop after k words have been output, if more than k words are present."
Given the text "A dog is a mammal and is a four legged creature", and the value k=2, the output is:
a is
"A complex piece of software consists of simple parts and simple relationships between those parts; the programmer's task is to state those parts and those relationships, in whatever order is best for human comprehension -- not in some rigidly determined order like top-down or bottom-up."
"My experiences have led me to believe that a person reading a program is ... ready to comprehend it by learning its various parts in approximately the order in which it was written."
"[Literate programming] ... allows a program to express programs in a `stream of consciousness' order." This contrasts programming languages that may enforce a particular order, such as top-down.
Literate programming is also good at separating an algorithm from its error-handling code:
if <input data is invalid> then
<Issue an error message and try to recover>;
<Update data structure using input>;
We use literate programming with our Chitra system for visualization and statistical analysis of trace data. We use C++, shell scripts, and a little FORTRAN.
I find today that I can locate the code that performs a certain function within 5 or 10 minutes. In class I'll show the table of contents of the main document.
In contrast, versions of two similar system written by students in past years was difficult to read and maintain.
"A program is best thought of as a web instead of a tree." [K, p. 107]
File containing literate program text (English plus code) is called a WEB file.
A WEB system strips out code, rearranges it to create compilable source code.
WEB will also write a file that can be processed by a text formatter, such as TeX.
There are several WEB implementations. We'll use funnelweb, which allows use of any programming langauge and (so far) two typesetters (TeX and html).
FunnelWeb allows user to control all aspects of formatting of source code that is generated.
This document will write the words "Hello World."
@O@<hello.txt@>@{Hello World@+@}
Try it and see.
In example above,
2. Run
fw hello
The output will be:
hello.lis - The LISTING file hello.txt - The PRODUCT file
3. To produce the typeset document, instead of step 2, do:
fw hello +t
The output will also include:
hello.tex - A DOCUMENTATION file (in TeX format)
Then do:
tex hello.tex
TeX then creates file "hello.dvi". 4. To view the typeset documentation file, do either:
dvips hello.dvi lpr hello.ps
or:
xdvi hello
Here's a longer example with macros. Symbols @$ denote a macro definition. Macros are delimited by @< and @>.
@O@<hello.c@>==@{@-
@<Include Files@>
@<Main Program@>
@}
@$@<Main Program@>==@{@-
main()
{
@<Print@>
@<Print@>
}
@}
@$@<Print@>==@{@-
printf("Hellow world!");
printf("\n");@}
@$@<Include Files@>==@{@-
#include <stdio.h>
#include <stdlib.h>
@}
Macros "Include Files", "Main Program", and "Print" have no parameters in this example.
Funnelweb parses and analyzes macros from input before expanding any macros.
Macros can take parameter lists. Parameters are denoted @1, @2, ....
Suppose we wanted each invocation of the Print macro to pass a different text to printf:
@$@<Print@>@(@1@)==@{@-
printf("@1");
printf("\n");@}
Then the Print macro would be invoked by:
@<Print@>@(
@"Hello world@"@)
or
@<Print@<@(Hello world@)
There can be up to 9 formal parameters (i.e., @1 to @9).
In class I'll go over the example on p. 27-28 of [W].
Questions on example:
Note in example:
'Cos I shoot with a camera instead of a gun.
The animals flock to be petted and fed,
and suppose that poem.fw contains:
I like to go shooting, it's a whole lot of fun,
@i camera.txt
Cos they know my camera isn't loaded with lead.
FunnelWeb will replace the @i line by the text in camera.txt:
I like to go shooting, it's a whole lot of fun,
'Cos I shoot with a camera instead of a gun,
The animals flock to be petted and fed,
Cos they know my camera isn't loaded with lead.
Note: FunnelWeb expands include files before it starts scanning and parsing included text.
These can be interspersed in any manner.
The @O directive controls the order in which the product file's text is generated. In contrast, the documentation file's order corresponds to the order of free text and macros in the .fw file.
A .fw file is hierarchically structured using section headings. These are specified by @A to @E.
@A is a new chapter.
Example 1:
@A@<How Tangle and Weave Work@>
@B@<How Tangle Works>
I need to write this section.
@B@<How Weave Works@>
And I need to write this section, too.
Example 2:
@B Notice that the heading was not given. It will be "How
Tangle Works" due to the macro definition below.
@$@<How Tangle Works@>==@{...@}
@{ ... @}
Example:
@{This text will be set in the font in which macros are set, which is a fixed-width font.@} This text will not.
@/ ... @/
Meanwhile, @/this text will be set in an emphasis font, such as italics.@/
@t new_page
The @t directives tell the typesetter to perform certain actions.
== define a macro in one part
+= define macro in multiple part
@A...@E section headings
@i include a file
@M signifies that a macro can be called multiple times
@O output text to product file named in following argument
@p give a pragma, such as:
indentation = none
@t entire line is a typesetter directive, such as:
new_page
table_of_contents
title titlefont|smalltitlefont|normalfont centre|left|right ...
vskip 40 mm
@Z signifies that a macro can be called zero times
@$ define a macro
@{@} delimit macro body OR sets free text in same font as
macros
@<@> either define a macro or call a macro
@/ delimits free text to be set in italics
@1...@9 actual parameter list
@" used to allow insertion of white space in actual parameters
@, used to separate actual parameters in a list
@(@) used to enclose parameter lists
@-@+ delete or insert newline character after this symbol
@= redefine special character (its default is "@")
@! comment line follows on remainder of line
(In class we'll look at the example in section 1.8 of [W] along with the TeX output. I'll pass a hardcopy of this out to you.)
The FunnelWeb User's Manual on many CS department machines is in:
/cruncher/u3/abrams/doc/fw_userman.dvi
View the manual by doing
xdvi /cruncher/u3/abrams/doc/fw_userman.dvi
The binary of FunnelWeb is named fw. There are binary versions of fw for several platforms in
/cruncher/u3/abrams/bin/<platform>/fw
where <platform> is alpha, mips, next, or sparc.
The /cruncher/u3/ is an nfs mounted file from cruncher to many DECstations in the CS department. It can be mounted on other machines that you use by request.
To use fw, you must have /cruncher/u3/abrams/bin/<platform> on your path.
Create a file containing the funnelweb input. Let it be called hello.fw.
Then execute:
fw hello +t
This will create three files:
hello.lis -- A listing file hello.tex -- A document file (in TeX format) hello.txt -- A product file
You can do "cat hello.txt" to look at the product file. To view the document file, run
tex hello
The file hello.dvi will be created (along with hello.log). You can view the file from X-windows with
xdvi hello &
You can print the file by first creating a postscript file (named hello.ps), and then spooling the postscript file to the printer:
dvips hello lpr hello.ps
You can put more than one @O into a literate program. Thus you can have one .fw file that creates multiple compile modules (e.g., .h and .c files).
You can put a @O into a .fw file that writes a manual entry for the command to a file.
@$@<Generic Node@>@(@2@)==@{
module @2;
type @2 = ^@2Record;
@2Record = record
Member: @1;
Next: @2;
end;
@}
@O<Node.pas@>==@{@-
<Generic Node@>@(integer,integerNode@)@}
@O<RealNode.pas@>==@{@-
<Generic Node@>@(real,realNode@)@}
class Node {
@<Private Part@>
public: void Insert(Node*);
}
(From [W], p. 53)
Scramble the program so that it is layed out in an unordered, undisciplined "stream of consciousness" style. Don't think about how to order your presentation.
Use the opposite of spaghetti organization. Lay out the program in order "desired" by programming language. Even if this order is appropriate, forget to make it descriptive.
Do not strike a balance between the needs of the first time (sequential) reader and the maintenance (random-access) programmer.
Make the document a network of facts, so that changing a small piece of code invalidates many pieces of text scattered throughout the document. Overuse the conversational style (mention things many times).
Whenever you begin a new section, and the section starts with a macro, and no commentary is needed, succum to the urge to fill the space between them with useless text.
If a piece of code is fairly self explanatory, give in to the urge to overdocument by writing a long commentary.
If you are generating product files that must exist on their own (i.e., the code will be used in a larger programming project that does not use literate programming), be sure to make the text and the code comments redundant. Even better, be inconsistent as to whether an important fact goes in the text or in the code.