Hacker News new | ask | show | jobs
by cxr 1124 days ago
> Does it matter though?

Yes.

> The primary purpose of using literate programming is expository.

Right. A big, zero-context block of includes prefaced with a comment that you should just "skip ahead" past it to the "interesting stuff" and offering no insight about the stuff that you're skipping over is the opposite of expository. The main program—what it actually does—is sufficient to serve as exposition for the includes that it ends up needing to be put it. So actually write it that way.

> That's the benefit of WEB[...] The presentation order is not dependent on the code order, it's dependent on what makes the most expository sense.

The argument is that it doesn't make expository sense to write the includes the way Knuth is. It's just yet another form, as taeric observes, of boilerplate—which makes us a slave to what the (LP-unaware) compiler expects, and which LP is supposed to liberating us from...

* * * *

It strikes me that there are probably only two ways to really deal with includes in the spirit of literate programming, which is to either (a) put them at the end after having already shown us why they're necessary (accompanied with with e.g. a comment along the lines of "Recall that our program is using printf—a part of the C standard library and defined in stdio.h—so it's necessary, therefore, that we include it in order for our program to compile") or (b) to use WEB/CWEB's appending facilities—after having written a routine that uses printf for the first time, you write an interlude not altogether different from what I just described that adds that include to the "running sum" of necessary includes, which the tangle step will take care of as part of the build.

(I say "only" because these are the only ways that occur to me that it can reasonably be done. I'm not committed to that being true—I'm open to the possibility of there being more—and it's not as if I started with that in mind, but it's hard for to imagine others. The only thing I'm really committed to is that what the article says about Knuth's two examples being wrong is accurate. I know Kartik has softened his stance since originally writing it, but I haven't. The examples given are individually each an awful way to demonstrate LP considering how antithetical that is to the whole thing. Totally indefensible.)

2 comments

My point, which you missed: It doesn't matter what Knuth does.

thr-nrg rightly pointed out in their comment that you can place the code wherever you want. You then say, "Knuth puts it at the top" (meant as a criticism of his style).

My point (so you don't miss it again): You can place the code wherever you want when doing a literate programming style. It also doesn't matter what Knuth does with his includes because his style does not dictate your style or my style or anyone else's style. So put it wherever you want. His style does not matter.

I didn't miss it. I replied to your question of whether it matters: yes, it does.

Your point doesn't make any sense. ("_You_ can place the code wherever _you_ want when doing a literate programming style.") Literate programs are supposed to be read. Of course a writer can write however they want. You could write a book where everything that isn't a proper noun ends with an uppercase letter, except for proper nouns, which are all lowercase. It will be shit.

What matters is the exposition. Does the presentation (order, style, etc.) communicate what you intend for it to communicate, and does it communicate effectively. That's what matters.

Does it matter what Knuth does? Nope. I don't care for that aspect of his style. I already said I put the includes (when a text gets past the draft stage at least) toward the end. We're in violent agreement with respect to how we (if I understood you correctly) often or generally put them into LP texts.

You're just weirdly caught up on criticizing Knuth's style for some reason. Have fun shouting into the wind. The rest of us know, it doesn't matter. The goal is to communicate effectively and not whine about things that don't matter.

I don't think I'm the one missing the point here. You're adamant that I'm complaining about Knuth's style. I'm complaining that programs he's written don't show us that exposition matters (rather than him just telling us that it does).

Exposition does matter. He's not doing it. That's the problem.

Dumping a big lump of include statements or defines at the beginning of the text and then saying don't worry about it isn't an example of someone who actually believes that exposition matters. It's incontrovertibly devoid of exposition—not just a matter of it being one's "style".

> What matters is the exposition.

> Does it matter what Knuth does? Nope.

Either it matters, or it doesn't. Pick one.

> Exposition does matter. He's not doing it. That's the problem.

I agree. Here's an example I give of an emacs configuration in the typical style which I don't find especially useful versus one that does use exposition:

https://www.paretooptimal.dev/finding-the-best-style-of-lite...

Here's a sample:

    * My emacs use-cases
    ** Version control with Git
    *** use magit as a porcelain
    #+begin_src elisp
     (use-package magit)
    #+end_src
    *** enable easily showing history of a file
    #+begin_src elisp
     (use-package git-time-machine)
    #+end_src
I'm not entirely sure that trying to not have boilerplate of any kind is a worthy goal. Consider, no book is wanting to get rid of the title page. Even a dedication page has grown to be a near required page that we literally teach students to write.

To that end, the goal is to not have parts that can be the same between programs vary. That has pedagogical value. Is a type of stability that we don't really value much anymore.

Though, I also give a +1 to jtsummers' point. Knuth has a style of writing literate programs. And if you find some old videos of his reviewing student's code, he explicitly calls out points of style that he likes from different students and how they work together. He didn't necessarily want to push a "this is how you style your programs," but instead was working how you talk about programs into a way that you can also write them. While not having to relearn either, necessarily.

> I'm not entirely sure that trying to not have boilerplate of any kind is a worthy goal.

I think it's a worthy goal for nearly all readers. However I also believe that literate programmers should be written with many different readers in mind.

So you could have one version that is written in a "typical code" style like:

    * library 1
    ** module 1
    *** source file 1
    ** module 2
    *** source file 2
That doesn't need to be where it ends though and arguably shouldn't be. Write multiple books using the same code but represented differently as it's justified.

For example:

    * typical program style
    ** library 1
    *** module 1
    **** source file 1
    *** module 2
    **** source file 2

    * new to language X presentation of program

    ** link to various parts of library 1 alongside prose to describe concepts to language newcomer

    * typical hire presentation of program

    ** business domain focused exposition presenting code via transclusion as needed from typical program style
People will inevitably complain that what you're advocating for involves too much duplication, but I've independently reached the same conclusion that you have. Besides, in a good LP system, the toolchain would be able to consume the second part and transform and emit the first part.

See also this conversation about the unreadability of Knuth's .web files: <https://news.ycombinator.com/item?id=29203798#29205840>

> Consider, no book is wanting to get rid of the title page.

Lists of imports are not title pages.

> the goal is to not have parts that can be the same between programs vary

Lists of imports vary. (And in today's world of extreme software reuse, which other pieces of software a program depends on is of greater interest than ever.)

I'd take your point on boilerplate if it were necessary and unavoidable. I've already described, however, that it isn't and how.

Depends on the list? The ones you linked from Knuth are basically fixed imports that are, in fact, very common and easy to take as a whole.

I think the disconnect is still that you are writing a C program with CWEB. If I'm using a literate style to write JavaScript, I'm still writing a JavaScript program. As such, the point isn't to just throw any established norms out, but to rearrange for presentation. If some items go well together, might as well keep them together.

Most programming tools that can do this require you to "bundle" things such that you have to have well formed containers, if you will. Having the "add this to a section" constructs really help, as then you can say things like "add this to the imports" the first time you have need of a new import. But, if you don't add any non-standard imports, you can forego doing that.

The other approach is to try and make everything implied, such that new users can skip any of the boilerplate and jump straight to programming. That is fine, for what it is, but does little to build understanding of the programs as a whole.

That said, I may have missed your described solution. I'm kind of scattershot today and not keeping fully on top of this. Apologies if I'm talking past you.