This is a short write-up for the zine about literate programming.
Literate programming is an approach to computer programming invented by Don Knuth. The idea is to simultaneously create both code and documentation as a single unified literate program. One then tangles the literate program in to source code, and weaves it in to documentation.
Here's the idea as an ASCII-tastic diagram.
literate
program
/ \
(tangle) / \ (weave)
/ \
code docs
In this little zine article, I want to show off a little hack-y bit of literate programming that my friend Dave Gauer put together called RubyLit: "A literate programming system in 35 lines of Ruby". Dave's system uses markdown as the syntax for the literate program, which can then contain code in arbitrary lanugages. The process of "weaving" is just compiling the markdown. The process of "tangling" is a bit more subtle.
To keep things simple, I'm going to illustrate with a straight forward "Hello, World!"
To make it easier on your eyes, I'll make some of the leading spaces visible using the ␣ character.
Here is a complete listing of a literate program hello-world.md
.
There are only three bits of syntax.
This is a very strange program.
The headers come after the main part!
␣␣␣␣␣<<Headers>>
␣␣␣␣␣<<Hello World>>
## Hello World
The Hello World program is an absolute classic.
It was made famous by the 1978 book The C Programming Language.
All it does is print "Hello, world!"
Let's put that in a string variable.
␣␣␣␣␣message = "Hello, world!"
Ruby uses this funny syntax `puts` for printing output.
You get used to it eventually.
␣␣␣␣␣puts message
## Headers
Headers are the boring part of the program.
Usually, they're called headers because they come at the start.
With literate programming, you can put the boring stuff last.
This line just tells bash to use `ruby` to intepret this file.
␣␣␣␣␣#!/usr/bin/env ruby
What are the three parts of syntax?
Anything beginning with ##
creates a new "chunk".
This syntax also introduces a sub-section in markdown
.
A chunk can contain various code blocks which begin with a single space ␣.
In the example above, I've started my lines with five spaces because markdown
renders them as verbatim code which looks nicer.
The code blocks inside chunks do not need to be consecutive; for example the declaration of message
and "puts message
" are in the same chunk.
Lastly, the name of a chunk surrounded with <<...>>
braces reproduces all the code from that chunk.
The rubylit
program "tangles" the code by printing out all the code blocks and recursively expanding the <<...>>
tags.
The example above would produce the following tangled ruby
program:
␣␣␣␣␣#!/usr/bin/env ruby
␣␣␣␣␣message = "Hello, world!"
␣␣␣␣␣puts message
And so we have a very convoluted way to produce a "Hello, world!" program. Why go to all this trouble? I think it's interesting to be able to talk about your code as you write it. Literate programming allows you to lay out your code base in a way that makes literary sense, and tells a story.
Another reason for doing this kind of writing is more Knuth-ian:
you can write math about what you are programming.
Knuth tends to write very mathematically heavy code.
And so, he has a good reason for wanting TeX
enabled commentary on his code.
Initially, Knuth developed a literate programming system which was constrained
to writing code in PASCAL
and outputting documentation in TeX
. Later, Silvio
Levy developped CWEB
which is a literate programming system for C
. As of 2024,
CWEB is still under active development;
the most recent release was 4.12 on 2024-08-12.
Norman Ramsey, a computer scientist at Tufts University, has been maintaining a
language agnostic literary programming environment called
noweb since 1989.
Is literate programming for everyone?
No.
Critics point out that the tooling around it is not great.
It doesn't scale especially well to huge projects with many authors.
(Though, Knuth did write TeX
as a literate program. It weaves to a book.)
And, there isn't much need.
People mostly seem to get by just writing comments.
Some freaks get by without comments!
I think that literate program is a lot of fun.
After you try it, you start thinking of coding in a different way.
Last year, I had a great time re-writing soc
as a literate program.
You can read that program here:
https://ctrl-c.club/~pgadey/notes/computers/#soc
<!---
I modified RubyLit a little to allow for more flexibility in generating files.
My version is available in: /home/pgadey/bin/rubylit.rb
.
If you want a copy, just cp
it!
How's that for software distribution?
-->