3 ms·
Thanks for reading. I understand what you mean, and I agree with you that what you identified is in some sense what literate programming is all about. I think d
by svat 8y ago
Thanks for reading. I understand what you mean, and I agree with you that what you identified is in some sense what literate programming is all about. I think debating whether that's precisely what is meant and is discussed as “abstraction” probably gets into motte-and-bailey (https://slatestarcodex.com/2014/11/03/all-in-all-another-brick-in-the-motte/?comments=false https://slatestarcodex.com/2014/11/03/all-in-all-another-bri...) territory: by defining “abstraction” sufficiently narrowly or sufficiently broadly, nearly anything being discussed in this thread can be said to be abstraction or not. For example, while here you're pointing out that giving a name to a bunch of consecutive lines of code is indeed abstraction (and I'm inclined to agree with you), currently the top comment on this thread argues that even splitting code into functions isn't “real” abstraction (https://news.ycombinator.com/item?id=19011659 https://news.ycombinator.com/item?id=19011659).
So instead of trying to define “abstraction”, let's try to discuss the tradeoffs: I think what we're discussing is abstractions that are “formal” and “strong” versus those that are “lightweight” and “flimsy”. Look at the original example in the post:
void main() {
// Do A.
...
// Do B.
...
// Do C.
...
// Do D.
...
// Do E.
...
}
One could argue that here too there is “abstraction”, via the comments: they identify and document some related lines of code as doing something. When we move to the rewritten example:
void bar() {
// Do C.
...
}
void foo() {
// Do B.
...
bar();
// Do D.
...
}
void main() {
// Do A.
...
foo();
// Do E.
...
}
what's changed is that these abstractions have become more formal, more solid: grouping code into a function (I just left a comment about this: https://news.ycombinator.com/item?id=19012979 https://news.ycombinator.com/item?id=19012979) (instead of just with a comment) is a form of abstraction provided by the language, with stronger guarantees, such as that foo() cannot use variables that occur internal to bar().
Literate programming is somewhere between the two. The sectioning it provides is not a language-level construct; it's just textual (macro) substitution, and if you wrote something like that in C++ with #defines, you'd probably get yelled at for doing something dangerous instead of the abstractions (like functions) that the language provides. The literate-programming sections are very “flimsy”: code in one section can and does use variables defined in another (note all the function's variables are defined in section 53, and the function also uses global variables like `buffer` and `hash`); there's a “goto found” in section 56 where the label “found” is defined in section 55.
Abstraction, beyond just naming/chunking, involves bringing into existence some new entity. The more “formal” this new entity is, the more you have to worry about things like: its place in, and relationship with, the rest of the system (e.g. what are all the function's callers); its interface/boundaries (under what circumstances does it make sense to call this function); how much of a clear meaning it has, and so on. With just a named section, there's less of that. The same things that make the latter kind of abstraction “flimsy” also make it have less cost.
- microtherion 8y agoI agree that literate programming chunks can be very leaky abstractions, and it's a good point that LP systems provide no guarantees whatsoever about interfaces. But for precisely that reason, LP chunking sometimes is useful in situations where procedural abstraction is limited: In algorithms where the various sections are connected with very wide interfaces. If all you have are procedures, you either pass around a big struct, or an enormous number of procedure arguments. In object oriented programming, the big struct is implicit in the self/this pointer. LP gives another alternative.
- svat 8y agoRight, I agree; that was exactly my point too. :-) Maybe I worded it poorly initially: The original post was about the cost of "heavy" abstractions (functions), instead of something lightweight like comments and naming. (In searching for "the cost of abstraction", I just now found another post by the author: http://250bpm.com/blog:86 http://250bpm.com/blog:86) I agreed with this, and gave literate programming and the programs of DEK as an example (an alternative to “formal” abstraction): a prominent programmer finding ways to achieve things with only chunking/“lightweight abstraction”. (BTW, the programs I mentioned also eschew other sorts of abstractions like abstract data types, e.g. all memory is laid out in huge arrays and manually managed — it seems to work for him. But that may have been a constraint of the language for all I know.)