You might be interested in my review. I'm a Haskeller at heart, although the review draws more from my formal methods background. Spoiler: his main example of a deep module is actually shallow.
https://www.pathsensitive.com/2018/10/book-review-philosophy...
Defining errors out of existence should be mandatory for all golang programs.
If he did, I agree with you, he was wrong about that. I also agree that the unix file API is probably not a good example.
But whether or not he did, I think the dissection of edge cases would be better off emphasizing that he's got something importantly right that goes against the typical "small modules" dogma. All else being equal, deeper modules are good--making too many overly small modules creates excessive integration points and reduces the advantages of modularity.
P.S. While I'm here, this is not really in response to the parent post, but the example in the article really does not do justice to Ousterhout's idea. While he does advocate sometimes just inlining code and criticizes the pervasive idea that you should shorten any method of more than n lines, the idea of deep modules involves more than just inlinining code.
I mean the spec is a lower bound on the size of the solution, right? Because if the solution were shorter than the spec, you could just use the solution as the new shorter spec.
I agree that blindly making lots of tiny things is bad, but his criteria for how to chunk modules is flawed.
Darmani, is it fair to say that each interface should pay us back for the trouble of defining it—and the more payback the better? And given that, accounting for the ROI is either very complex work, or just intuitive gut instinct—as you point out in the Chicken nuggets example?
On the one hand, this is the stuff of religious wars. On the other hand, I see value in having a mental model that at least prompts our intuition to ask the questions: What is this costing? And how much value is it adding? And how does that compare to some completely different way of designing this system?
E.g., for users of certain systems, the cost of a GC may be roughly 0 as measured by intuition. I'm thinking of a system where the performance impact is in the "I don't care" zone, and no one is giving a single thought to optimizing memory management. For other users in other contexts, the rest of the interface of the GC becomes relevant and incurs so much cost that the system would be simpler overall without garbage collection.
Many other systems sit somewhere in between, where a few hot loops or a few production issues require lots of pain and deep understanding of GC behavior, but 99% of users' work can be blissfully ignorant about that.
And in many of these contexts, well-informed intuition might be the best available measurement tool for assessing costs and benefits.
> each interface should pay us back for the trouble of defining it—and the more payback the better
This seems to be the core question of this comment. I'll make the boring claim that every piece of code should pay us back for the trouble of defining it, which doesn't leave much more to say in response.
An important thing in this kind of conversation is to keep clear track of whether you're talking about the general idea of an interface (the affordances offered by something for using it and the corresponding promises) or the specific programming construct that uses the "interface" keyword. When you talk about defining an interface, you could mean either.
Another thing to remember is that, when you use "interface" in the former sense, everything has an infinite number of interfaces. For example, your fridge offers a dense map of the different temperatures and humidities at each spot. You could "learn this interface" by mapping it out with sensors, and then you can take full advantage of that interface to keep your veggies slightly fresher and have your meat be defrosted in exactly 36.5 hours. But if you get that information, there are countless ways to forget pieces and go from "the back left of the bottom shelf tends to be 35-36 F" to "the entire back of the bottom shelf tends to be somewhere between 0.5 and 2 degrees colder than the top of the fridge" down to "idk the fridge just keeps stuff cold." These are examples of the infinitely many interfaces you can use your fridge at, each offering a different exact set of abilities, most of which are irrelevant for the average user.
It's not, you're just ignoring what he said:
"A modern implementation of the Unix I/O interface requires hundreds of thousands of lines of code, which address complex issues such as: [... 7 bullet points ...] All these issues, and many more, are handled by the Unix file system implementation; they are invisible to programmers who invoke the system calls."
So sure, the `open` interface is big in isolation but when compared to its implementation it's tiny, which is what you've badly missed.
The book also brings up another example right after this one, that of a Garbage Collector: "This module has no interface at all; it works invisibly behind the scenes to reclaim unused memory. [...] The implementation of a garbage collector is quite complex, but the complexity is hidden from programmers using the language". Cherry picking, cherry picking.
Then you proceed to not mention all the other key insights the book talks about and make up your own example of a stack data structure not being a deep abstraction. Yes, it's not. So? The book specifically emphasizes not applying its advice indiscriminately to every single problem; almost every chapter has a "Taking it too far" section that shows counterexamples.
Just so you don't attempt to muddy the waters here by claiming that to be a cop-out, the very point of such books is provide advice that applies in general, in most cases, for 80% of the scenarios. That is very much true for this book.
Overall, your formal background betrays you. Your POV is too mechanical, attempting to fit the book's practical advice into some sort of a rigid academic formula. Real world problems are too complex for such a simplified rigid framework.
Indeed, a big reason why the book is so outstanding is how wonderfully practical it is despite John Ousterhout's strong academical background. He's exceptional in his ability to bring his more formal insights into the realm of real world engineering. A breath of fresh air.
I don't have much to say to most of your comment --- a lot of the text reads to me like a rather uncharitable description of the pedagogical intent of most of my writing.
I'll just respond to the part about deep modules, which brings up two interesting lessons.
First, you really can't describe an implementation of the Unix IO interface as being hundreds of thousands of lines.
That's because most of those lines serve many purposes.
Say you're a McDonalds accountant, and you need to compute how much a Big Mac costs. There's the marginal ingredients and labor. But then there's everything else: real estate, inventory, and marketing. You can say that 4 cents of the cost of every menu item went to running a recent ad campaign. But you can also say: that ad was about Chicken McNuggets, so we should say 30 cents of the cost of Chicken McNuggets went to that ad campaign, and 0 cents of everything else. Congratulations! You've just made Big Macs more profitable.
That's the classic problem of the field of cost accounting, which teaches that profit is a fictional number for any firm that has more than one product. The objective number is contribution, which only considers the marginal cost specific to a single product.
Deciding how many lines a certain feature takes is an isomorphic problem. Crediting the entire complexity of the file system implementation to its POSIX bindings -- actually, a fraction of the POSIX bindings affected by the filesystem -- is similar to deciding that the entire marketing, real estate, and logistics budgets of McDonalds are a cost of Chicken McNuggets but not of Big Macs. There is a lot of code there, but, as in cost accounting, there is no definitive way to decide how much to credit to any specific feature.
All you can objectively discuss is the contribution, i.e.: the marginal code needed to support a single function. I confess that I have not calculated the contribution of any implementation of open() other than the model in SibylFS. But Ousterhout will need to do so in order to say that the POSIX file API is as deep as he claims.
Second, it's not at all true that a garbage collector has no interface. GCs actually have a massive interface. The confusion here stems from a different source.
Programmers of memory-managed languages do not use the GC. They use a system that uses the GC. Ousterhout's claim is similar to saying that renaming a file has no interface, because the user of Mac's Finder app does not need to write any code to do so. You can at best ask: what interface does the system provide to the end-user for accessing some functionality? For Finder, it would be the keybindings and UI to rename a file. For a memory-managed language, it's everything the programmer can do that affects memory usage (variable allocations, scoping, ability to return a heap-allocated object from a function, etc), as well as forms of direct access such as finalizers and weak references. If you want to optimize memory usage in a memory-managed language, you have a lot to think about. That's the interface to the end user.
If you want to look at the actual interface of a GC, you need to look at the runtime implementation, and how the rest of the runtime interfaces with the GC. And it's massive -- GC is a cross-cutting concern that influences a very large portion of the runtime code. It's been a while since I've worked with the internals of any modern runtime, but, off the top of my head, the compiler needs to emit write barriers and code that traps when the GC is executing, while the runtime needs to use indirection for many pointer accesses (if it's a moving GC). Heck, any user of the JNI needs to interface indirectly with the GC. It's the reason JNI code uses a special type to reference Java objects instead of an ordinary pointer.
If you tally up the lines needed to implement either the GC or the POSIX file API vs. a full spec of its guaranteed behavior, you may very well find the implementation is longer. But it's far from as simple a matter as Ousterhout claims.
I too have a fp background and I felt the author is unqualified to talk about complexity without knowing fp. Elimination of procedures and mutations is a formal and concrete reduction of complexity while the authors definition of complexity is hand wavy. Someone should know about what fp is before writing a book like this.
Why? Because fp is a basically like a formal structure for software design and the author tried to talk about philosophy without knowing some hard formal rules that are well known in the industry. Not saying these rules are absolute but you can’t talk about design without talking about this.
The book talks about modularity and things of that nature too and totally skips out on understanding the separation between statefulness and logic. The author completely misses this design concept of how how IO and mutation should be separated from declarative operations. Imperative shell/functional core is a central design philosophy that he doesn’t touch upon. The book is woefully incomplete without talking about this. Whether the authors philosophy aligns with it is open for debate but you can’t talk about what he talks about without mentioning this in a big way.
Segregate mutation from logic
Segregate IO from logic
Eliminate procedures from logic.
The third axiom is sort of for free as it falls out automatically when someone enforces the first two. That’s basically imperative shell/functional core design philosophy which is basically identical to the rules of pure functional programming.
https://medium.com/ssense-tech/a-look-at-the-functional-core...
With fp you can think of these rules enforced as a language. Outside of fp we call it functional core / imperative shell and these rules can be enforced in an imperative language as a core design philosophy.
What are your favorite books on software design, functional programming, and/or computing generally? What are your favorite papers on the topic of complexity (as FP defines it)?
Following these philosophical principles themselves- it seems like a simpler and more accessible treatment of these ideas would be vastly more effective then a more rigorous and complete one- because the ideas are indeed simple.
It’s similar to why a big portion of the world believes in Christianity and another portion believes in Buddhism. Basically only one or none of these religions is correct rendering at least one population of people believing in a completely made up fantasy concept.
Much of what is preached in software is religion and what is preached by the majority can be completely ludicrous. The majority believing or not knowing something doesn’t mean anything.
The same is true for software design- an approach is not literally true or false, but either works for its intended purpose or does not. Conflicting philosophies can both be “true” just with different underlying goals or values.
To circle back here, my point is that this information is presented in a simple way that will let people reading it design better software. Saying they have no right to present it without a much less accessible and more complex framework that would likely make it less useful to the intended audience does not make sense to me.
FWIW, I am also a functional programmer, but would love to see people that are not follow some of these ideas.
——
There is only one kind of truth. “All truths are God’s truths.”
If Christianity is not true, then it is false. If Christianity and Buddhism strictly contradict each-other, then at most one of them is true.
Christianity is not meant to be a, what, psychological trick? It makes claims, and these claims should be believed if true and disbelieved if false.
I posit almost all intelligent monastics and religious people are smart enough to tell the difference between objective truth and religious truth- but it is taboo to explain this to lay people as they will be confused and think it means the religion is "fake" or a "trick", however I don't feel the need to respect said taboo. Perhaps I will learn to respect it by trying to explain it to people unsuccessfully.
[1] David Chapman may be able to: https://vividness.live/visionary-and-objective-truths
That is positing a conspiracy theory level of deception.
At least as far as Christianity goes, the "intelligent monastics and religious people" write down their beliefs, and have done so for millennia, and they read each others writings. What you suggest might be possible with an oral tradition, but not with a written one. Christianity is very much concerned with objective truth, and one of the distinguishing characters of it (and some other religions too) is a belief that there is an objective truth.
There's no deception- it's something that (as this discussion shows) is very subtle and dangerous to the religions when misunderstood- but not dangerous when understood correctly. It is written down repeatedly in religious texts, in a subtle way with plausible deniability, but clear to those that can read between the lines. Writing in that way was the essential basic art of any intellectual until very recently, it is only now (sort of) safe to plainly state nuanced philosophical and religious concepts without facing persecution. Nietzsche argued you still should not do so even if you can.
It's also both quite obvious and relatively unimportant on its own to people that would be capable of understanding nuance, and could be quite harmful to the faith and the stability of the religion of those not able to understand.
Can you give me an example of what you mean? From Christianity, as its the religion I know most about.
However St. Augustine is someone that I am particularly certain had a clear understanding of this, and I can see it in how he frames most of his ideas.
Another example, would be that ancient religious texts are not careful at all to avoid making numerous objectively factual contradictions- as the anti-christian crowd loves to point out over and over while also completely missing the point. If the people writing them thought that was important, they would have avoided doing so- contrary to modern opinion, ancient theologians and philosophers like St. Augustine were not idiots.
William Blake is a more modern person that, while just about the furthest thing from a monastic, clearly had a deep understanding of what I am talking about. Carl Jung also extensively understood and discussed a lot of esoteric things in Christianity including this, and wrote about them in a relatively clear modern way.
Can you give me an example of one?
> To me as a young kid, it was immediately obvious that there were deeper ethical principles being explained in these stories, and one had to be an idiot to be worried about if they were objective factual details or not
Again, an example? You are suggesting for example that there is no redemption or afterlife but they convey some point?
> If the people writing them thought that was important, they would have avoided doing so- contrary to modern opinion, ancient theologians and philosophers like St. Augustine were not idiots.
Does Augustine contradict himself? In a single work (different views in different works could be a change of mind)?
> You are suggesting for example that there is no redemption or afterlife
I am suggesting no such thing, only that dwelling on this issue is to miss the point, and even worrying about it would be an obstacle. One must deeply feel these ideas and practice accordingly to follow this spiritual path- even getting stuck on arguing that they are true would be an obstacle to that.
Myself, I would say I am non-religious, but have a lot of respect for the purpose and value religions offers people, and that one benefits greatly by understanding and filling those roles and needs in other ways even if not practicing a religion. I very much dislike the Richard Dawkins follower crowd that hate religion with a passion, but have no understanding of it, and have no connection to or understanding of their own emotions, unconscious, or spirituality to their own detriment.
https://www.smbc-comics.com/comic/2010-06-05
It makes a humourous and compelling argument that a big part of Christianity is encouraging its adherents to follow the game-theoretic optimum in a way that will convince someone even if they are a bit credulous.
If you approach the bible with a good knowledge of negotiation and game theory, a lot of it can be interpreted in that light. There is a lot of good advice to get people to move to the global optimums that can be reached if everyone cooperates. It isn't subtle about it. There is no conspiracy to hide that it is good advice even to someone who doesn't particularly believe in afterlives, miracles or god-given ethics. There is a very neat division between the common read and the read of someone with a good grasp of social dynamics, negotiation and game theory. No conspiracies. Just a lot of people who can't handle complex social negotiation.
There is also a lack of evidence it works. I do not think Christians are consistently greatly more socially cooperative than atheists. Maybe more inclined to help people on the fringes of society - e.g. running food banks here in the UK, very active in poverty charities globally but while good, I cannot believe it has a sufficient consistent effect to provide an advantage to a society that follows it.
Fear of hell as a motivator is limited to some Christian denominations but is not often mentioned by other denominations (I am mostly familiar with Catholic and Anglican churches) or in the Bible, or Christian writings, or in sermons or in religious discussions. Christian universalists and others do not believe in any form of hell at all!
It might work with a religion once established (religious societies do better because of that cooperation) but it does not explain how religions spread in the first place. Its a lot more likely to apply to a religion that has been long established in a relatively stable setting so it is credible as an explanation of much of ancient Jewish law that seems strange to us now (e.g. what to eat, not plucking fruit from young trees etc) that often seems off from a modern perspective.
One example theory I remember reading at some point was the prohibition against eating shellfish: In the area the religion arose, it would have most likely gone bad by the time it was brought that far inland.
Shellfish are susceptible to harmful algal blooms like red tide, that can make them very dangerous.
Coastal foraging cultures that don't have bans on eating shellfish, instead have complex knowledge about when, where, and how to prepare and eat them. It's the same with mushrooms- cultures either universally ban them, or deeply educate everyone about them. All cultures globally with access to these foods have a system here- it's not unique to Judaism.
I take a Jungian view that a major useful thing religions offer is a framework for relating to the unconscious. One key part of that is to have a clear sense of ethics, and to align ones actions with it, which is generally good for your mental health.
Take CS Lewis as an example. He write strong and clear defences of the incarnation, miracles etc. as objective facts. He was either trying to deliberately deceive or he did not actually understand older writing, and the latter is not really credible given he was the professor of mediaeval and renaissance literature at Oxford.
> The mystique of this is openly part of the draw for people to sign up for it.
Not in my experience of priests, monks and nuns and people who consider becoming clergy.
Another possibility is that if you get what I'm saying here, you might re-read CS Lewis and have a very different perspective on what he was actually saying- because those Christian "truths" are extremely important, and exist for a good reason - and one can write a strong clear defense of them from the perspective I am coming from.
I read a lot of old philosophy and religious texts translated and commented on by "well respected" scholars, and it is not uncommon at all that I can tell they are seeing only the surface of the ideas... which can make it frustrating and difficult to read when the translator wasn't 'getting it.' The level one needs to be at to be a well respected philosopher, and just to succeed as an academic are not close at all, and there is no guarantee that the latter will be capable of fully grasping the ideas of the former - it is probably the norm that they cannot. If they could they would not be just a translator or scholar, but a powerful philosopher in their own right.
An intelligent person whose mind is fundamentally oriented towards communicating deeper meaning, does not operate on the level of obsessing over banal binary verification of facts- and they need to be able to assume their reader is already capable of thinking abstractly in this way as well. To put it simply one must assume intelligence in the reader to communicate deep ideas and meaning, and neglecting to "explain how to be intelligent" is not deception- when it is not even something that can be explained.
It might be better to think of it as a potentially useful fiction. Our culture is full of those.
Morality doesn't exist in any objective sense, which means "murder is wrong" is not, strictly speaking, true. That doesn't mean it isn't useful for us to collectively treat it as if it's true. You might even argue that that's the nature of all shared truth.
Yeah, I'm disagreeing with that passage.
> [I]f Christ has not been raised, our preaching is useless and so is your faith
Faith can be useful even when it does not reflect an objective truth. In fact, you might say that faith can only exist at all in the absence of objective truth. I don't need to have faith that a triangle has 3 sides, or that ice is cold.
If we do take seriously the idea that Christianity must either be true or false, then it's obviously false: Most religions contradict each other, and none of them have any concrete evidence in their defence. The natural conclusion is that all religious beliefs are false. But then we have to interpret society as a place where most people believe obvious falsehoods, which is just not a useful lens. There is a huge difference between a falsehood like "triangles have 5 sides" and a falsehood like "Jesus was reborn." Nobody would believe the former, but many people believe the latter. We must distinguish useful fictions as a category beyond the dichotomy of simple truth or falsehood.
You have picked religions with as little as possible in common. It would be rather different if you had picked any two monotheistic religions for example: one could be entirely right, and that would mean the other was partially or mostly right.. Despite your choice, there are many things in common: a path to redemption, monasticism, wealth being a barrier to redemption, meditation and mysticism... its quite possible those common elements might be right.
The same with software. Some things that are widely believed may be true and other false.
Parent is telling you: "if A is so simple and obvious, why does nobody do A", your counter argument: "if many people believe A it does not mean it is true". This is entirely unrelated, the point is that these things are NOT obvious to the average programmer, he/she would benefit from learning this, and claiming that these things are broadly "stupid and obvious" is petty and false.
Also, the things you're saying just don't add up with your criticism that the author is missing some fundamental part of software philosophy. If the author is only missing something, then it still makes sense for the majority to learn the things he is saying, at least, as explained by your parent.
Finally, if anything can be compared to religion, it surely is the evangelism of functional programming zealots.
> If the author is only missing something, then it still makes sense for the majority to learn the things he is saying, at least, as explained by your parent.
Sure but from my pov he’s teaching mathematics while skipping over algebra or addition. We can all agree that something huge is missing if you don’t learn algebra or addition.
> Finally, if anything can be compared to religion, it surely is the evangelism of functional programming zealots.
I don’t deny it. Nobody can really prove their viewpoint to be true. Even the atheist is a zealot. The only way to not be a zealot is to be a zealot about being unsure of everything. But then that makes you a zealot. People insinutated a lot of things because I used religion as an analogy.
The ONLY point I was trying to make is that a majority or large group of people believing in or doing plan A doesn't mean shit for plan A.
I don't think you understand either the parent or me. The point is that the majority of people do something wrong that the author is trying to help prevent, so just by virtue of that being true it stops being "stupid and obvious".
> We can all agree that something huge is missing if you don’t learn algebra or addition.
We can indeed all agree on a separate topic, but that does nothing for the topic we are actually discussing. The core of your entire argument is that somehow FP is fundamental to solving complexity, you seem to think that everybody already agrees with this. We don't.
> Even the atheist is a zealot
No, he is not. Being an atheist or not is a completely internal world view, being a zealot implies being vocal and aiming to convert or convince others.
> The only way to not be a zealot is to be a zealot about being unsure of everything
No this is also not true, see above. Things are not as black and white as you think.
> People insinutated a lot of things because I used religion as an analogy.
The point of an analogy is to improve the discussion through clarity, you made a bad analogy and in doing so made the discussion worse and less clear.
> The ONLY point I was trying to make is that a majority or large group of people believing in or doing plan A doesn't mean shit for plan A.
Which, again, is missing the point. The majority is already judged by the parent, namely: they are doing something wrong. Hence it does not matter that the majority is not always right, the point of the parent is already that the majority is wrong. You are trying to argue for something that nobody brought up, you are arguing against the statement: "the book is good because everybody is doing what it describes". Nobody is saying that, and so you're arguing into the void.
On “Missing the Point” You keep insisting I’ve misunderstood the parent, when in fact I’m the one highlighting the exact same oversight the parent (and you) are making: popularity of a method—or “everyone doing it”—doesn’t prove correctness. You’re so busy telling me I’m off-target that you’ve inadvertently circled right back to my original statement. Bravo for that rhetorical pirouette.
The Religion Analogy My analogy wasn’t about the specifics of Buddhism vs. Christianity any more than referencing “Homer’s Odyssey” requires you to believe in sea monsters. An analogy’s job is to illustrate a point. You chose to interpret it literally, which is about as productive as reading a metaphor and then complaining it’s not a physics textbook. If you can’t separate form from function, maybe you shouldn’t be lecturing people on clarity.
FP, Zealotry, and the Real Topic It’s downright adorable that you think I’m pushing some “everyone agrees FP solves everything” agenda. I specifically said “nobody can prove a viewpoint absolutely”—which you just argued against by, ironically, claiming some vantage of universal correctness. This might be the first time I’ve seen someone label atheists as ‘not zealots,’ then turn around and call me one for not fitting neatly into your black-and-white categories. The mental gymnastics are impressive—Olympic-level, even.
Majority vs. Correctness You keep shouting that the majority is wrong, that the book is aiming to correct them, and that somehow I’m “arguing into the void.” Yet my entire point (and this is the third time I’ve repeated it, but apparently you need a replay) is that a majority doing something doesn’t automatically validate or invalidate a claim. And guess what? You agree. You literally said the majority is wrong. So if I’m “missing the point,” then so are you—just from the opposite side of the mirror.
On Being a Zealot Contrary to what you claim, being “vocal” about something doesn’t automatically make you a zealot any more than whispering your opinions makes you right. If you’re content to wander around in that nuance-free zone where anyone with a perspective is a fanatic, you’re welcome to it. Just don’t be surprised when folks point out that you’re holding an umbrella indoors to avoid a hypothetical downpour.
In short, you’re so determined to prove me wrong that you’ve ended up echoing my very premise—that “everyone doing X” doesn’t magically prove X is correct—while scolding me for saying precisely that. Next time, maybe aim for consistency before you break out the condescension. It’ll save you the trouble of repeatedly shooting down a position you’re already occupying.
also, just because someone writes poor code doesn't mean they don't know how to write good code - intent isn't always clear, and it's a mistake to assume ignorance based only on the output
1. Are you quite sure John Ousterhout (who invented Tcl[1], comparing it to Lisp in section 7 of the original paper) doesn't "know about what fp is" as you say?
2. Do you think that the main reason functional programming hasn't taken off in systems programming is that practitioners are ignorant, or do you think there might be issues with fp systems that prevent its adoption?
[1] https://web.stanford.edu/~ouster/cgi-bin/papers/tcl-usenix.p...
Fp with lisp is only a fraction of fp. I of course am talking more along the lines of pure fp which lisp is not.
But omitting fp in the book is not evidence that Ousterhout is ignorant of fp, and there is certainly evidence to the contrary.
The likely explanation, given that he's developed a number of systems from Sprite to Tcl/Tk to RAMCloud to HOMA, is that he is addressing the current practice of systems programming, which remains primarily imperative.
I acknowledge that he does not cover purity and mutations as a source of complexity (and they are big sources of complexity) but I don't think that merits dismissing the entire book on those grounds.
Because it misses these concepts the book isn’t good in my opinion.
If the book had been titled "Formal methods for software design" the lack of algorithms for reducing complexity would have been surprising. As it is about philosophy it should not be surprising that it focuses on heuristics.
It’s a core heuristic and philosophy that is foundational in my opinion. The author failing to mention this makes the book missing a fundamental issue central to software design.
I agree with you that the separation of Church and state is a foundational idea of software design and even computing generally. I find it quite beautiful how it manifests in hardware as the two categories of digital logic - combinatorial and sequential. And if we zoom in on the logical expression of memory we see it again - a latch is simply two feedback loops and some combinational logic.
For what it's worth I thought the book was brilliant. Its ideas weren't all obvious to me before I read it. It also inspired me to read Parnas, Wirth, Hoare, and study the Go runtime and compiler.
What should be obvious is this: the fact that the ideas were obvious to you doesn't mean they are obvious to everyone.
Secondly, complexity has many meanings. Managing complexity is incredibly important in the realm of security. I've been dabbling in security for 25 years, but I would certainly not claim to have a deep understanding of functional programming. Nevertheless I understand complexity quite well. I think that's what bothered me the most about your original comment - the idea that people without a background in FP are unqualified to talk about complexity.
From a philosophy-of-complexity perspective it's not needed, all you need to ask is: will my code give the same output given the same input? (And if not, there's your complexity!)
Of course, this is a big ask of a programmer. Leaving determinism up to the programmer in an imperative setting is like leaving memory-safety up to the programmer in a C setting.