> should be taken more as an endorsement of his skill than the tools
Or that Knuth, as smart as he is, has not been able to transmit and explain to you how to do what he is actually doing (only what he thinks he is doing by, for example, outside/indirect observation).
Or maybe the literate approach is better for thinking in english (and perhaps mathematics) and then verifying it in each (tiny) software module.
I've spent a lot of time thinking about what skills are actually needed here, maybe not as much time as Knuth has, but I have the benefit of learning from his work: I don't use a literate style (indeed, I prefer the much more compact style[1]) and I don't have a strong mathematics background.
What I do is try to make my programs as small as possible so that it's simply not possible for any bugs to hide in them. Yes that means whitespace, not binary size. Then I compose my application out of a few small programs.
I sat on the plane recently next to a guy proofreading a manuscript. He had five phones out next to his laptop, all with various parts of his document open on them, scrolling on each. I didn't want to disturb him to ask him what he was thinking, but was nonetheless fascinated by his process.
I intend to try experimenting with a lot of little displays for my programs next.
[1]: https://github.com/geocar/dash/blob/master/d.c#L61
> One of my favourite examples of this is APL, where those experienced can read and write programs in it as easily as they can a human language; programs which are completely incomprehensible to anyone who doesn't know the language.
APL has got anywhere from 30-70 or so builtins (depending on how you count and the specific flavour of APL) and a very simple syntax. I think a lot of their "incomprehensibility" comes from how strange they look. If a literate approach can be useful for training a mathematician uncomfortable with programming Java and C# to use Java and C# effectively, then perhaps it can be used for teaching APL.
Assuming you have a dictionary of your alphabet:
A←'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPRQSTUVWXYZ0123456789'
and a way to collect the contiguous "words" from some input:
words←{1↓¨(~x∊A)⊂x←' ',⍵}input
which is easy to understand if you break it up; the key part is `x∊A` which generates a bitmap of the locations where our input is a member(∊) of our alphabet. We negate(~) it since we want the breaks, and then we then take that bitmap and pick(⊃) out the breaks. Note I put something not in the alphabet at the beginning of the input so that `x` will begin with a break.
Next we'll want the unique words without an empty word (likely if we have multiple breaks in a row):
unique←(∪words)~⊂''
and to know how many there are:
counts←+/unique∘.≡words
By doing a match on each word against the unique word `∘.≡` we build a 2d bitmap which is as wide as length of the unique words, and as tall as the number of words - each cell denoting whether the word was the unique word we were comparing. You might try `unique∘.≡words` for yourself.
Lastly, we want the indices of the top (3) counts:
i←3↑⍒counts
so that we can draw a nice table of the results:
(⍪unique[i]),⍪counts[i]
You can try this at
http://tryapl.com/K/Q has a slightly simpler solution since it has a builtin "group" operator and more data types (like dictionaries), if you have something that makes words
words:{"<"vs ssr[x;"[\000-@\133-`\173-~]";"<"]}
it's a simple matter to take some number (3) of the descending count of each group or:
3#desc count each group words input
or in k:
a!x a:3#>x:#:'=words input
which you can try by downloading the free version at
https://kx.com