Literate Programming Example
This is the result of my recent research on Literate Programming in Racket. The name of this file is LPexample.scrbl. Initially, I struggled with broken links, but that problem has been solved.
LPexample.rkt is the source file for this document. The Github repository is here.
1 Introduction
Racket’s scribble/lp language allows programs to be written in the Literate Programming Idiom. The documentation, however, is not very clear. This should not be particularly surprising because Racket’s documentation is sometimes lacking when it comes to features outside the core and when something between very basic material and detailed reference is needed.
2 Weaving
The process of weaving is where scribble/lp is a bit confusing. Unlike documents in scribble/base or scribble/manual, documents written in scribble/lp cannot be directly rendered to HTML or LaTeX. This is why DrRacket does not provide "the easy button" when it sees a scribble/lp document.
Documents written using #lang scribble/lp use the file extension .rkt not .scrbl.
@(require(for-label 2htdp/image)) |
@require[scribble/lp-include] |
@title{Literate Programming Example} |
This is the result of my recent research on Literate Programming in Racket. The name of this file is @code{LPexample.scrbl}. It's not perfect as I still have not solved the problem of broken links, but I'm working on it. |
@lp-include["LPexample.rkt"] |
The file for weaving has a file extension of .scrbl. To weave LPexample.rkt we run the scribble command on its corresponding .scrbl file. In this case: LPexample.scrbl.
Resolving the external references has two parts.
The first is (require(for-label 2htdp/image)) which sets the documentation phase references. The documentation phase in Racket is analogous to the expansion phase for macros in Racket and other Lisps in that it just focuses on modifying the source code rather than compiling it.
- The second step is calling the scribble command with the appropriate flags. The command to weave this document is:scribble --html +m --redirect-main http://docs.racket-lang.org/ LPexample.scrbl
3 Tangling
@chunk[<example_main> |
<example_requires> |
<example_exports> |
<example_body>] |
Which matches the source for this output from the weaving process:
@chunk |
@chunk |
@chunk[<*> |
<example_requires> |
<example_exports> |
<example_body>] |
can be placed anywhere in the document to serve as the main chunk. Having tried it, it really doesn’t add anything for clarity and is unnecessary.
The reason it is unnecessary is that tangling can entail composing the code in a sequence other than what would normally be used in a #lang racket program. For example, required modules need not be near the top. This chunk:
@chunk[<example_importExport> |
(require 2htdp/image) |
(provide (all-defined-out))] |
produces, this output from the weaving process:
(require 2htdp/image) (provide (all-defined-out))
@chunk[<blue_square> |
(rectangle 100 100 "solid" "blue") |
which weaves to this:
(rectangle 100 100 "solid" "blue")
@chunk[<blue_square> |
(beside/align "bottom" |
(ellipse 20 70 "solid" "lightsteelblue") |
<blue_square>)] |
which weaves out to:
(beside/align "bottom" (ellipse 20 70 "solid" "lightsteelblue") <blue_square>)
4 Conclusions
Weaving requires a second file where a file with a .rkt file extension is referenced using lp-include.
Tangling treats the first chunk differently unless the <*> special name is used.
Happy Literate Programming, Ben.
Update: 13/12/19 - broken links issue fixed and documented thanks to StackOverflow user Asumu Takikawa.