Literate programming can take various forms. I am working on a survey
of literate software. I came across an interesting non-latex example
worth sharing:
http://jashkenas.github.com/coffee-script/documentation/docs/nodes.html
Notice how well they have documented an apparently simple line as in:
exports.Base = class Base
The Base is an abstract base class for all nodes in the syntax tree.
Each subclass implements the compileNode method, which performs the
code generation for that node. To compile a node to JavaScript, call
compile on it, which wraps compileNode in some generic extra smarts,
to know when the generated code needs to be wrapping up in a
closure. An options hash is passed and cloned throughout, containing
information about the environment from higher in the tree (such as
if a returned value is being requested by the surrounding function),
information about the current scope, and indentation level.
Notice how this is not only giving trivial information (e.g. Base is
an abstract base class) but WHY it exists (..as a base for all nodes in
the syntax tree). It gives operational information (to compile a node..)
as well as information about the effect (..which wraps...). It shows
how global information is used (An options hash..) and WHY (containing
information about the environment...)
Code only tells you HOW something is done at the time it is done.
It's like having a recipe without an idea what you would make.
If our standards of documentation were raised to this level then large
systems like Axiom, Clojure, and ClojureScript would be much easier to
maintain and modify in the long term.
If you want your code to live beyond you, make it literate.
Tim Daly
da...@literatesoftware.com
or the original paper
www.literateprogramming.com/knuthweb.pdf
or from the master himself:
http://www-cs-faculty.stanford.edu/~uno/lp.html
Tim Daly
I recall that at some point you described your setup for doing Clojure
literate programming, and if I recall correctly, you were primarily
working in LaTeX, relying on incremental compilation to test little
snippets of code as you wrote them.
Have there been any new developments on the literate programming /
Clojure front, in terms of tools that leverage existing build tools,
test suites, generating meaningful line numbers for stack traces and
debugging?
Yes, the idea is to write a literate version of Clojure, see
http://daly.literatesoftware.com/clojure.pamphlet
http://daly.literatesoftware.com/clojure.pdf
similar in style to "Lisp in Small Pieces". (The effort has been
stalled temporarily while I try to find new employment.)
>From the above document you extract the Makefile, type 'make'
and end up with the newly formatted PDF and a running REPL.
So any edits to the document text are immediately reflected in
the PDF and any edits to the code are immediately reflected in
the compiled results.
>
> Have there been any new developments on the literate programming /
> Clojure front, in terms of tools that leverage existing build tools,
> test suites, generating meaningful line numbers for stack traces and
> debugging?
>
The question is ill-posed in sense that literate programming is not
a tool or technology but a change in mindset. To quote Knuth:
I believe that the time is ripe for significantly better documentation
of programs, and that we can best achieve this by considering programs
to be works of literature. Hence, my title "Literate Programming".
Let us change our traditional attitude to the construction of
programs: Instead of imagining that our main task is to instruct
a computer what to do, let us concentrate rather on explaining to
human beings what we want a computer to do.
-- Donald Knuth "Literate Programming (1984) CSLI 1992 pg. 99
So imagine a world where the eloquence of Rich Hickey was expressed in
book form. Imagine the whole immutability lecture written down and
decorated with the actual running code as illustration. Imagine that
the original authors clearly explained software transactional memory
and illustrated it with the actual code. Imagine a discussion of
argument destructuring with running code illustrations.
How many more people would be able to dive into the details of Clojure
to maintain and modify the code? How many people would find it much
easier to understand prototypes, defrecords, macros, and all of the
other struggles that populate the current email forums? How are
infinite sequences supported and what code supports it? What does
NIL mean and why was it defined that way?
We do not capture the ideas. We do not rewrite the explanations to
clarify the fine points of confusion. We do not illustrate how the
ideas of Red-Black tries are moved "from ideas to implementation".
We do not communicate the ideas to each other. We code for the machine.
So we end up with the traditional "tree of sand" pile of little files.
In order to overcome this we construct tools (IDEs) that know how to
navigate this pile, tools to store the changes (SVN, git, hg), tools
to put the sandpiles together (#include), tools to build guardrails,
tools, tools, tools... (You can, of course, keep each chapter and
section and subsection in separate files and "include" them in the
book.)
Now imagine that the "book" is multimedia where you can include
animation (watch the tree balance), video, and a running REPL.
Think Khan Academy for Clojure.
This community is willing to overthrow the traditional ideas of lisp
in order to make progress on a new path. Yet we continue to structure
the development as though we worked on a PDP 11/40 with 4k file size
limits. We continue to let the most valuable information which is the
meat of Clojure disappear while we keep only the code, the bones of
Clojure.
Open the source code. Stare at it. Ask yourself if you understand
exactly why it was needed, why it is structured that way, what would
happen if you changed it and what else depends on this code. Imagine
your job is to maintain and modify it but Rich is not available for
questions and answers.
Ultimately that is what matters. In the long term the code will be
the only remaining artifact after Rich leaves the project. Look at
Sourceforge and you will see thousands of dead projects that will
never be picked up because they are just trees of code, dead code.
Et tu, Clojure?
Literate programming is about making code live.
I like Clojure and I really want it to live.
Think long term. Imagine a better way.
Tim Daly
So imagine a world where the eloquence of Rich Hickey was expressed in
book form. Imagine the whole immutability lecture written down and
decorated with the actual running code as illustration. Imagine that
the original authors clearly explained software transactional memory
and illustrated it with the actual code. Imagine a discussion of
argument destructuring with running code illustrations.How many more people would be able to dive into the details of Clojure
to maintain and modify the code? How many people would find it much
easier to understand prototypes, defrecords, macros, and all of the
other struggles that populate the current email forums? How are
infinite sequences supported and what code supports it? What does
NIL mean and why was it defined that way?We do not capture the ideas. We do not rewrite the explanations to
clarify the fine points of confusion. We do not illustrate how the
ideas of Red-Black tries are moved "from ideas to implementation".
We do not communicate the ideas to each other. We code for the machine.
--
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clo...@googlegroups.com
Note that posts from new members are moderated - please be patient with your first post.
To unsubscribe from this group, send email to
clojure+u...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
Off the Beaten Path in Technology
http://otbeatenpath.wordpress.com
--
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clo...@googlegroups.com
Note that posts from new members are moderated - please be patient with your first post.
To unsubscribe from this group, send email to
clojure+u...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
On Thu, 2011-10-27 at 20:11 -0400, Larry Johnson wrote:
> My two favorite articles on Literate Programming are both from Donald
> Knuth's book Literate Programming. One is "Computer Programming as an
> Art", and the other is "Literate Programming". When I was preparing
> to interview Knuth a bit over a year ago I re-read the entire book. I
> expected it to be a somewhat outdated description of WEB, TANGLE, and
> WEAVE. On the contrary it was wonderfully timeless. When I mentioned
> that to Knuth he sort of grumbled something to the effect of "Well,
> yes, some things in computer science have a long shelf life" (that's a
> paraphrase, but it was something like that).
Knuth's invention of literate programming is one of the unrecognized
pearls of computer science. I have yet to see a programming team that
has an Editor-in-Chief who does patch-review for clarity, sentence
structure, punctuation, relevance, location in the book, proper
citations and index terms, etc. Maybe someday.
>
> I haven't been working with it for awhile, but I did a somewhat
> primitive modification to the XML Docbook markup language (I just
> added a few appropriate tags for "tangling" the executable source
> code, and "weaving" the well formatted article documenting the code)
> which I used as the source language, then wrote a tangle and weave in
> perl. I got the idea from Norman Walsh's article Literate Programming
> in XML which can be found at
> http://nwalsh.com/docs/articles/xml2002/lp/paper.html
>
> The advantage of this was that given the array of tools for rendering
> Docbook "weaving" was a piece of cake, and perl had a good range of
> modules for doing the "tangle".
Any means of publication can be the medium for literate programming.
As I rule I prefer Latex but anything will do.
All you need is a distinguished means of quoting and naming the
chunks. In html this could be as simple as:
<pre id="somename">
your code
</pre>
and you need a program, often called "tangle", to extract the chunk
tangle mywebpage.html somename >mysomename.file
The machinery of literate programming is dirt simple.
Poof! You're done.
The hardest part of literate programming is the mindset.
In order to do literate programming you need to change your focus
from traditional programming to writing for humans and, as a side
effect, writing for the machine.
>
> As I stated, I'm very new to clojure, but I've always been fascinated
> with LP, and I'm very happy to see this discussion going on here.
Java has taken the PDP 11/40 sand files to their logical extreme where
we have wired the name of the tiny file to the name of the tiny object.
We have packaged the automobile into a crate with labeled bags of
screws, hoses, switches, etc. and are expected to understand the car.
Clojure is a very early adoptive, open minded community willing to
challenge old assumptions. It helps to highlight what those old
assumptions are, as Rich has done for Lisp, since they can be
difficult to see and hard to displace. I am hoping the community
will disrupt the tiny-files, javadoc, IDE, code-for-the-machine,
mindset and start communicating with humans. Rich has great ideas
in Clojure and all we get is the dried bones of source code.
We can do so much better.
Tim Daly
http://orgmode.org/
git://orgmode.org/org-mode.git
Here are some things I've used it for:
http://aurellem.com/abomination/html/no_parens.html
http://aurellem.com/pokemon-types/html/lpsolve.html
http://aurellem.com/thoughts/html/man-years.html
It's possible to automatically monitor the org files in a project,
regenerate the html and source code whenever they are changed, and get
a very tight write-debug-test cycle. Try it out it's fun!
sincerely,
--Robert McIntyre
Any means of publication can be the medium for literate programming.
As I rule I prefer Latex but anything will do.
All you need is a distinguished means of quoting and naming the
chunks. In html this could be as simple as:
<pre id="somename">
your code
</pre>
and you need a program, often called "tangle", to extract the chunk
tangle mywebpage.html somename >mysomename.file
while I agree that good documentation is important for maintaining and
developing further a given code base, I always wonder how literate
programming deals with refactoring and larger restructuring. I mean, in
basically all software projects I'm involved in, developers have a hard
time in keeping at least the most integral documentation up-to-date,
e.g., docstrings, JavaDocs, etc.
Now I consider a some literate code base, i.e., a book that describes
the complete system in a very detailed manner including the reasons to
design it that way. That's awesome for developers joining the project,
but doesn't it hinder any further development?
For example, I'm currently reworking some paper that includes code for
some model transformation. If I had the right tools, I could extract
the source code from the latex files and have a running transformation.
But now, I had to do some minor modifications to the code which took me
about 5 minutes, but adapting the surrounding text takes me hours over
hours. I think, that's an experience many people have made: changing
source code of a system that is well-designed and understood by the
developer is much easier to do than changing a cohesive text in natural
language. In code, I have an automated, picky lector that always reads
the complete "book" after each change I make (also known as compiler).
In plain text, only a human can verify consistency and only in very
narrow borders.
Well, that's more text than I intended to write. ;-) So short story
long: how do you manage conistency of docs and code in literate code
bases?
Bye,
Tassilo
Hard work? Book authors face the same problem. Every new change to
Clojure makes more work for the authors.
One side-effect of Literate Programming is that you re-arrange your
code to fit the presentation. As a result you bring together chunks
that are all related (e.g. the code to support Red-Black tries).
I would claim that refactoring "in the large" is unlikely in a
literate program because you have to think through the code in order
to explain it clearly. But if you do a large refactor then it is
just hard work. For small refactorings you might not have to change
the explanation at all.
Clojure is pretty well "firmed up" at this point. I don't know if
there is going to be a large rewrite of the fundamentals.
Tim Daly
I think my question is legitimate.
To take an extreme example, if you tell me literate programming is
great, but that I have to write out my programs by hand on paper and
scan them into a computer, I'd laugh at you. Why would I want to give
up the convenience of typing in my programs via keyboard to do
literate programming?
So I'd like an honest appraisal of the state of the art in literate
programming of Clojure -- what tools and conveniences do I have to
give up to do LP. Do I have to give up things like meaningful line
numbers when I get an error message?
I'm not sure what tools you use for development. Straight emacs is
sufficient for my development. Emacs doesn't care what style is used
for development.
>
> So I'd like an honest appraisal of the state of the art in literate
> programming of Clojure -- what tools and conveniences do I have to
> give up to do LP. Do I have to give up things like meaningful line
> numbers when I get an error message?
>
State of the art in literate programming in Clojure?
Hmmm. The pamphlet link is my only example of literate programming
related to Clojure. In order to develop you edit the pamphlet, type
"make" at a command line, and the world is rebuilt. Since the code is
extracted into the same source tree as it originally had, the line
numbers will be related to the file and line as before.
My development style involves changing about 10 lines of code or less
followed by a complete system rebuild and test cycle. Overlapping
rebuild and test is time for writing the literate explanations.
Almost always, when something fails it is perfectly clear what lines
caused the error. When that isn't the case then a little "navel
debugging" (contemplating what might be wrong) is used.
I don't use IDEs but I suppose it would be possible to write a
literate plugin of some kind that ignored things that were not in
code chunks. Line numbers could then be interpreted with respect
to the start of the chunk. Most IDEs allow plugins.
To your point, though, it is true that we may have reached a local
optimum of tool development for tiny files. It might be necessary
to move away from this peak in order to climb a different hill.
This would imply making things "worse" for development until the
tools adapt. Clojure moved off the local optimum of common lisp
and broke all my code-walking software, violated quite a few of my
assumptions, and invalidated my manuals but that isn't an argument
for abandoning Clojure.
You might feel that the current toolset is optimal and that
literate programming is not worth the time and effort.
De gustibus non disputandum. (There is no disputing taste).
A literate Clojure would only be of benefit to those who come after.
All it offers now is a lot of time and effort to communicate ideas
to people we will never meet. However the thing that draws people
to Clojure is the ideas, not the code.
We can debate it at length over beers at the Conj.
Tim Daly
Clojure moved off the local optimum of common lisp
I have also been using Emacs/Org-mode/Babel/R lately, mostly as a way to have easily modifiable write up and source code for assignments in statistics courses. I suppose this is one valid use, but I'm using it less to communicate code meaning and more as a convenient way to perform analysis, look at the results, and talk about them all in the same place, and then to easily generate documentation of my efforts [LaTeX output].
Damion
I'm not sure what this sentence means. The .tex files ARE the
literate program. By analogy, you seem to be asking something like
"I'm writing a book but I don't know where to put the text".
>
>
> The combination of literate + TDD seems forbidding.
Are you finding it hard to explain why you wrote a test?
Tim Daly
Are you finding it hard to explain why you wrote a test?
>
> The combination of literate + TDD seems forbidding.
Tim Daly
Untangling woven text is trivial. It can be done in any language. See
http://axiom-developer.org/axiom-website/litprog.html
> and ask the person I'm talking with to imagine writing an article or
> book about their code, how it works, with proofs where appropriate.
> That article should be written as a work of literature. Not all
> literature has to be Hugo or Melville (or Jack Kerouac, or Gertrude
> Stein for that matter). Some programs are more appropriately Mickey
> Spillane or Terry Pratchett, or even in the style of a manual for an
> electric razor. The point is that it should be satisfying to read and
> comprehensively informative.
>
> Test code, and descriptions of external libraries are no different
> from any other sections of the article or book. The most important
> thing is to introduce them into the work at point most conducive to
> the reader's understanding.
If a test is testing something worthwhile, as opposed to the "blindly
testing that 3=3" mindset, then it probably only takes a couple lines
to motivate why you need the test. A test paragraph could contain the
details. So if you're writing a hash table implementation, the test
code of overflow chaining could explain what problems might occur (e.g.
what happens when the table is actually full? How do you detect that
the overflow chain has looped?, etc.)
So if you wrote the hash table implementation code in literate form
then each test could explain (and test) a particular boundary case or
issue that might arise.
This has the effect of motivating tests that are detailed, based on
real issues, and handle boundary cases clearly.
>
> I really believe that there's no programming or engineering
> methodology which doesn't lend itself to literate programming. If it
> can be described, it can be presented in the form of an article. If
> it can't be describe in human language it's probably terrible code.
Test cases don't have to appear as "test cases". They appear in the
text as either example code (useful for the reader but also testing)
or as explanations of possible failures, misuse, misapplication, or
boundary cases.
This is especially powerful if you focus your tests on
precondition/postcondition testing. See Hoare's paper
"An Axiomatic Basis for Computer Programming"
http://citeseer.ist.psu.edu/viewdoc/summary?doi=10.1.1.116.2392
Using Hoare's ideas to focus the development of your test cases means
that your tests have a good theoretical basis. They check for the
conditions that should survive refactoring. Requiring precondition
postcondition tests, along with clearly written natural language
explanations, could be part of the peer code review prior to
accepting new or revised code into the main line.
Better yet, in a literate program, you can explain what the invariant
is, why it is important, and what breaks when you violate it. So
testing now has a good formal basis rather than random 3=3 tests.
We can be so much better programmers.
Raise your game.
Be literate.
Tim Daly
What a great idea!
I'll see what I can do.
Tim Daly
Seems to me that the structure is this:
A string that's written language is some alternating form like
word separator word separator ...
where a "word" consists of consecutive alphanumeric characters and a
"separator" consists of consecutive nonalphanumeric characters. The
separators in this paragraph include " ", " \"", "\" ", ". ", and " \"
\", \" \\\"\", \"\\\" \", \". \", ", as well as one more that I can't
add here without generating one more still.
One tends sometimes to want to split a string in such a fashion,
transform the words only, and then reassemble.
This in turn suggests tools like:
(wordify string) -> a seq of strings starting with a separator and
alternating words and separators. The initial separator may be "".
Something like (map #(apply str %) (group-by alphanumeric? string))
with alphanumeric? testing a character, but if the first character of
the first string in the output seq is alphanumeric, a (cons "" %)
needs to be done on the output before returning it.
(map-words* f wordified-string) -> (interleave (take-nth 2
wordified-string) (map f (take-nth 2 (next wordified-string))))
(map-words f string) -> (apply str (map-words* f (wordify string)))
or similar.