#lang scribble/doc @(require "common.ss" (prefix-in c: "collatz-doc.ss") scribble/struct) @title[#:tag "literate"]{Literate Programming} The techniques used for in-source documentation extend to the creation of WEB-like literate programming tools. @Figure-ref["Collatz"] shows an example use of our literate-programming library; the left-hand side shows a screenshot of DrScheme editing the source code for a short, literate discussion of the Collatz conjecture, while the right-hand side shows the rendered output. Literate programs written with our library look like ordinary Scribble documents, except that they start with @code-elem|{#lang scribble/lp}| and use @scheme[chunk] to introduce a piece of the implementation. A use of @scheme[chunk] consists of a name followed by definitions and/or expressions: @code-block|{ @chunk[ ... definitions ... ... expressions ...] }| @no-indent The definitions and expressions in a chunk can refer to other chunks by their names. Unlike a normal Scribble program, running a @schememodname[scribble/lp] program ignores the prose exposition and instead evaluates the program in the chunks. In literate programming terminology, this process is called @defterm{tangling} the program. Thus, to a client module, a literate program behaves just like its illiterate variant. The compiled form of a literate program does not contain any of the documentation, nor does it depend on the runtime support for Scribble, just as if an extra-linguistic tangler had been used. Consequently, the literate implementation suffers no overhead due to the prose. To recover the prose, the @code-block|{@lp-include[_filename]}| @no-indent form extracts a literate view of the program from @scheme[_filename]. In literate programming terminology, this process is called @defterm{weaving} the program. The right-hand side of @Figure-ref["Collatz"] shows the woven version of the code in the screenshot. Both weaving and tangling with @schememodname[scribble/lp] work at the level of syntactic extensions, and not in terms of manipulating source text. As a result, the language for writing prose is extensible, because Scribble libraries such as @schememodname[scribble/manual] can be imported into the document. The language for implementing the program is also obviously extensible, because a chunk can include imports from other PLT Scheme libraries. Finally, even the bridge between the prose and the implementation is extensible, because the document author can create new syntactic forms that expand to a mixture of prose, implementation, and uses of @scheme[chunk]. Tangling via syntactic extension also enables many tools for Scheme programs to automatically apply to literate Scheme programs. The arrows in @Figure-ref["Collatz"]'s screenshot demonstrate how DrScheme can draw arrows from chunk bindings to chunk references, and from the binding occurrence of an identifier to its bound occurrences, even across chunks. These latter arrows are particularly helpful with literate programs, where lexical scope is sometimes obscured by the way that textually disparate fragments of a program are eventually tangled into the same scope. DrScheme's interactive REPL, test-case coverage support, module browser, executable generation, and other tools also work on literate programs. To gain some experience with non-trivial literate programming in Scribble, we have written a 34-page literate program that describes our implementation of the Chat Noir game, which is distributed with PLT Scheme. The source is included in the distribution as @filepath{chat-noir-literate.ss}, and the rendered output is in the help system and online at @show-link{http://docs.plt-scheme.org/games/chat-noir.html}. @(figure** "Collatz" "Literate programming example" (make-table '((row-styles . ([(style . ("Half" "Half"))]))) ; custom cell styles to improve HTML output (list (list (make-flow (list (make-paragraph (list "")) (make-paragraph (list (image #:scale .6 "collatz.png"))))) (make-flow (list (lp-minipage (make-splice (flow-paragraphs (part-flow c:doc))))))))))