Writing, n.

2011-03-24 15:01:56 UTC

Over on Tumblr (where I have also started writing), Andy Matuschak and Christopher Bowns have challenged each other:

Long story short: Andy and I threw down our respective gloves after throwing back the third glass of whiskey, and came up with this: every Tuesday, we’ll spend 20 minutes of our respective shuttle rides to work writing something. It doesn’t matter what, but when those 20 minutes are up, you publish it.

After Christopher published that, Colin Barrett entered with this piece. Discussion ensued on Twitter, as it so often does, and it included this tweet from Christopher:

@cbarrett Perfect. I think “overthinking it” can cripple your writing, but it’s hard to let go of, because it’s so useful in engineering.

I responded there, but I’d now like to expand in a somewhat different direction here.

Writing programs is writing.

Consider this: If you write a program that no human can read, you have written it badly, and may have even written an outright bad program. Switch out “program” for “manuscript” and I hope you see my point.

Don’t confuse this with literate programming. That has you write a more-or-less human-only text, and then run a program such as WEB or CWEB to translate it to source code.

The problem with literate programming is the problem with all translation from one language to another, especially automatic translation: Error.

Just as translating a human-only text from one human language to another human language can produce a garbled mash, so can translating a program from one language to another produce a nonsense, or at least broken, program.

Hence the justified suspicion of programs that “upgrade” a program even just from one version of the same language to another: It isn’t the same language; not really. Similar, but not the same. Going from Python 2 to Python 3, for example, is not much different from going from 18th-century English to 21st-century English. Do these words mean the same thing? Maybe not. This is why such translators invariably come with warnings to check the hell out of the result.

No, I’m not talking about literate programming. I’m talking about regular programming, where you write the true text of the program, the text that the interpreter interprets or the compiler converts into machine code.*

Programming is a fusion of a couple of skills. It’s often called “software engineering”, but that’s only half of it. Writing is the other half. I define “writing” here as writing text into an editor, whatever the language, and “engineering” as designing a thing to be built. Things like OOP, unit testing, and design patterns are aspects of software engineering. Things like DRY, commenting practices, naming practices, and style rules are aspects of writing.

If you write a program well, you write it not only for the interpreter or compiler, but for any humans who will read the program after you, including yourself. It is a text like any other.

Writing a program is writing. Every rule, observation, and prescription you apply to writing for humans only, apply also to programming, and vice versa. If the rule does not work, chances are it was not a good rule to begin with.


Suggested reading


* This is, itself, a form of translation; the C standard even calls it such. That’s part of why compiler bugs are possible, and why compiler authors are extremely careful about their work, which is why compiler bugs are so rare.

4 Responses to “Writing, n.”

  1. Colin Barrett Says:

    I find literate programming fascinating, and it turns out Haskell has native support for it.

    http://www.haskell.org/haskellwiki/Literate_programming

    No translation required.

  2. Peter Hosey Says:

    Colin: That’s not literate programming, though; it’s just using LaTeX instead of plain text for comments. There’s no reason you couldn’t have a tool to do that for any language.

    Literate programming, as Knuth described it, is more sophisticated. You aren’t simply mixing human-only text with code; the written program defines macros as chunks of code, and uses these macros to effectively be programmed in a human language, such as English. You have a preprocessor that expands the macros and cuts out the human-only text, “tangling” the program from the original version to the version that will actually be compiled.

    It’s a neat idea in theory, but, according to the post by Greg Wilson that I linked to, the problem comes when you try to debug it, because the version that crashed or worked incorrectly is not the version you wrote—it’s a translation. You have to work on the translation and then translate your changes back. (Imagine heavily using C preprocessor macros and then having to debug based on the preprocessed output.) Pain in the ass.

    Haskell’s “literate programming” doesn’t have that problem because it’s not literate programming; it’s just documentation-mixed-with-(the-final-)code.

    The closest C/Objective-C analogs of that Haskell tool are HeaderDoc and Doxygen.

  3. Colin Barrett Says:

    No, you don’t have it quite right. Basically, .lhs files assume everything is a “comment”, unless you indicate otherwise (the reverse of normal, where everything is source unless you indicate it’s a comment). This means you can feed an .lhs file directly to LaTeX as well as directly to a Haskell compiler or interpreter. No additional tools are required. This has little to do with HeaderDoc or Doxygen.

    My understanding of literate programming is very basic, but whether or not the tools Knuth was using and the ones built-in to the Haskell standard are the same is kind of beside the point — the intent was to provide a way to write a single prose document with source snippets inside it and produce both runnable code and a fully formatted document. .lhs files accomplish this. End of story, as far as I’m concerned :)

  4. Peter Hosey Says:

    Basically, .lhs files assume everything is a “comment”, unless you indicate otherwise (the reverse of normal, where everything is source unless you indicate it’s a comment).

    This difference is unimportant.

    This means you can feed an .lhs file directly to LaTeX as well as directly to a Haskell compiler or interpreter. No additional tools are required.

    This difference is also unimportant.

    … the intent was to provide a way to write a single prose document with source snippets inside it and produce both runnable code and a fully formatted document. .lhs files accomplish this.

    The important difference is that .lhs (and HeaderDoc and Doxygen) simply alternate between comments/documentation and source code. There’s no intelligence to it; all it does is switch between copying the input and not copying.

    Literate programming as defined by Knuth uses a macro system. You set chunks of source code as the values of the macros, name the macros with human-language phrases, and describe the program not only by writing comments, but by using the macros.

    Reading that last paragraph back to myself, it sounds like we have replaced literate programming with good function/method naming mixed with verbose comments. No additional tools or special compiler support needed, you get the same benefit to readability, and it’s much more debuggable, and you can do it in any language with sane (i.e., generous) name-length limits.

Leave a Reply

Do not delete the second sentence.