Your abstraction isn't wrong, it's just really bad

by George16 min read26th May 202017 comments

24

World Modeling
Frontpage

Epistemtic status: pretty sure

For a programming language to qualify as such, the only thing it needs is Turing Completeness. That means, at least in principle, it can be used to solve any (solvable) computational problem.

There are features besides Turing Completeness which make it desirable, but if you tried hard enough, all of those features could be implemented as part of any Turing complete language.

Let's take a maximally perverse theory of abstraction-making that says:

An abstraction is sufficiently good if, in principle, it can yield answers to all questions that it's designed to solve.

Under this definition, the assembly language (ASM) of virtually any computer is sufficient abstraction for writing code.

The only "problem" with ASM is that writing something simple like quicksort ends up being monstrously large and hard to read (and this implementation is written for clarity, not speed).

Compare that to a quicksort implementation written in, C. It's only 13 lines of code and about as equally efficient as the ASM one above. Even better, it would work on virtually all machines, while the above ASM wouldn't and would have to be rewritten for a bunch of architectures.

C might not be the best abstraction one can use for low-level programming, e.g. writing sorting algorithms, but it's better than ASM.

However the ASM implementation is far from being the maximally perverse version one can get under our naive abstraction-choosing constraints. The prize for that would currently go to something like the brainfuck implementation:

>>+>>>>>,[>+>>,]>+[--[+<<<-]<[<+>-]<[<[->[<<<+>>>>+<-]<<[>>+>[->]<<[<] <-]>]>>>+<[[-]<[>+<-]<]>[[>>>]+<<<-<[<<[<<<]>>+>[>>>]<-]<<[<<<]>[>>[>> >]<+<<[<<<]>-]]+<<<]+[->>>]>>]>>[.>>>] 

Now that, that is what I call seriously fucked up.

But brainfuck is Turing complete, so under the above definition, it is no worse than ASM or C.

How we avoid bad languages?

So C, C++, Javascript, Python, Julia, any given ASM, Fortran, Lua, Elm, Clojure, CLISP, Rust, Forth, Elixir, Erlang, Go, Nim, Scala, Ada, Cobolt, Brainfuck, and, sadly enough, even Java, are "good enough to be an abstraction for controlling ANY computing systems" under the perverse requirements above.

In reality, it's fairly easy to agree that some languages are better than others in various situations. I think most criteria for choosing a language are at least somewhat subjective. Things such as:

  • Architectures that the compiler will target
  • Memory safety features.
  • Built-in parallelism and concurrency mechanisms.
  • Functionality of standard library.
  • Available package manager.
  • The companies/projects/communities that already use it.
  • Ease of learning.
  • Ease of reading.
  • Ease of debugging.
  • Speed of compiler[s].
  • Efficiency of memory usage (e.g. via avoiding spurious pointers and having move semantics).
  • Performance on various benchmarks.
  • What I want to use the language for (which is probably the most important).

But even subjective criteria allows me to ask a question like: "What do I need in order to create a language that is better than C and C++ for systems programming?". To which the answer will be something like:

  • Be Turing complete
  • Support all or most targets that C/C++ support
  • Have memory safety feature (e.g. borrow checking, automatic deallocation) that C and C++ don't have.
  • Have the same concurrency abstractions as C and C++ (Threads mapping to kernel threads)) and maybe some extra ones (e.g. futures and async-io semantics for more efficient non-blocking IO).
  • Have a standard library that includes all glibc and std-lib functionality plus some extra things that people want.
  • Have a package manager.
  • Try to make nice companies and welcoming communities that are viewed well by outsiders use your language.
  • Have better, more centralized documentation than C/C++ and community that is nicer and more helpful to newbies.
  • Try to be about as easy to read as C and C++, ideally more so by getting rid of BC syntax and outdated operators.
  • Have a good debugger and nice error logs, or at least nicer than C and C++.
  • {Try} to have a fast compiler.
  • Be about as efficient as C and C++ when working with memory, potentially making useful abstractions (e.g. moving, deallocation) implicit instead of explicit whenever possible. Perhaps by using a better default allocator.
  • Perform equally~ish well to C and C++ on various benchmarks that people trust
  • Be useable in the same situations C and C++ are, maybe more, if possible. This is partially a function of all of the above plus the external library ecosystem, which the language designer can nudge but has no direct control of.

What I describe above is, of course, Rust. A language that, with certain caveats, has managed to become better than C and C++[citation needed] for systems programming (and many other things).

Granted, the world hasn't been rewritten in Rust yet. (Though I hear the R.E.S.F has managed to secure an audience with God and given his buy-in, you'd be only one level removed from converting von Neuman.)

But it does have wide adoption and I would be deeply surprised if in 10-20 years from now most server kernels and common low-level libraries (e.g. BLAS, CUDNN) won't be written in it.

For a more post factum example, you can take something like Python, due to a good package manager and easy to understand syntax, it managed to become the dominant scripting language for... everything.

For another example, take Nodejs, which used people's familiarity with javascript and it's build-in asyncio capabilities to become the language of choice for many low-load http servers.

Or take something simpler, like TypeScript, which just took Javascript, added a feature people really, really wanted (types), and swiftly became a fairly dominant language in the frontend world.

Our model for avoiding bad languages is based on continuous improvement and competition. You look at what existing language are used for and what people want to do with them, you look at their syntax and their performance. Then you build something that fits the basic requirements (is Turing complete, runs on x86) and tries to be better than then them in the pain points previously identified. If your new language is good enough, it will sweep everyone away and 10 years from now we'll all be using it.

A similar but less complex set of criteria can be defined for libraries and open-source software in general. A similar but more complex set of criteria can be defined for processor and computer architectures.

The languages, processors, and libraries of the 80s are all "kinda bad" by modern standards. The ones of the 40s are basically at the brainfuck levels of horribleness. But this is not to say that the people of the 80s or 40s were bad programmers, it's just that they didn't have the knowledge and tools that we have right now.

Indeed, I'd wager that the pioneers of computer science were probably smarter than the people doing it now, successful pioneers tend to be that way, but seeing mistakes in hindsight is much easier than predicting them.

The requirements for avoiding bad abstraction

So, I think the requirements for avoiding bad abstraction, at least in terms of programming languages and programming abstractions in general, can be boiled down to:

  1. Minimal and rather specific core standards (Turing completeness, ability to run on a popular~ish CPU).
  2. Ability to name areas where improvements can be made such that the language could be considered "better" than current ones.
  3. A general willingness of the community to adopt the language. Or at least a mechanism by which the community can be forced to adopt it (see market-driven competition).

Granted, these requirements are far from being fulfilled perfectly. The adage still holds mostly true:

Science progresses one funeral at a time

Programming languages are not quite like scientific paradigms, partially because the field they are used in is far more competitive, partially because they are much easier to design than a scientific theory.

An average programmer might switch between using 2 or 3 significantly different languages in one area over their lifetime. An especially good one might bring that number to 10, 20, or 50 (most of which are going to be failed experiments).

There's no programming God that can just say "X is obviously better than Y so switch all Y code to X and start using X". There is however something close to an efficient market that says something like:

If I can design a piece of software in 1 hour using my language and you can design it in 100 hours using yours, I will soon build a 3 person startup that will eat your mid-sized corporation for lunch.

However, I don't want to downplay the role that community plays here.

Imagine designing a new language and trying to improve and popularize it, you'll need validation and feedback. In general, the reactions you will get will probably be neutral to positive.

Being already popular and respected helps (see Mozzila and Rust), but so does having a language that seems very obvious useful by filling a niche (see frontend devs wanting to work full-stack and Node) or just having an amazing syntax (see Python way back when). However, the worst-case scenario is that you end up getting some "oh that's nice BUT ..." style reactions and are left with a good learning experience as the basis for your next attempt.

I don't think anyone ever tried to build a programming language (or a library or a CPU arch for that matter) and was met with:

Oh, you stupid quack, you think you're better than the thousands of language designers and dozens of millions of developers building and using a programming language. You really think you've managed to out-smart so many people and come up with a better language/library !?

I think that the lack of this reaction is good. However, try to challenge and redesign a core abstraction of any other field (internal medicine, high-energy physics, astronomy, metabolic biology... etc) and that's roughly the reaction you will get. Unless you are a very respected scientist, in which case you will usually get indifference instead and maybe in 60 years, after the death of a few generations, your abstractions will start being adopted. But this is a very subjective impression.

On the other hand, good CS students are routinely challenged to design their language and compiler. Maybe 999/1,000 times it sucks, but that's ok because they get a better understanding of why our current languages are good and of the principles behind them. Even better, maybe 1/1,000 times you get the seeds of something like Scala.

I have it on good authority that no physics students were ever tasked with trying to re-design the mathematical apparatus used to interpret the results of high energy collisions into taxonomical facts.

We make fun of tools, but in general, we never make fun of tool-creation. Creating tools for programming (e.g. language and libraries) is as close as you can get to a sacrament in the programming community. It's something that's subconsciously seen as so desirable that nobody has anything but praise for the attempt (though, again, the results are fair game for harsh critique).

Note: Of course, outliers exist everywhere, including here.

Is your abstraction bad?

So the reasons we know our programming abstractions (e.g. languages and libraries) are kind of good is that we have a market mechanism to promote them, a culture that encourages and helps their creation, and both explicit and implicit criteria that we can judge them by.

We don't know how good they are in an absolute sense, we can be almost certain they are not the best, but we can be 100% sure that they are not the worst, because we know they aren't Brainfuck.

But take away any piece of the puzzle and the whole edifice crumbles, or at least is badly damaged. If you replace the free-market determination with a council of elders or a regulatory board, then Node and Python don't exist. If you replace the community with one that is trying to minimize the amount of new things they have to learn, then Rust doesn't. If the quality criteria were much fuzzier than we might have just stopped at ASM instructions and never designed any language.

This is the fear I have about a lot of other abstractions.

Take for example taxonomies in fields like biology and medicine.

There's a taxonomy that clusters things that can approximately replicate the contents of DNA and RNA molecules encased within them into: Realm > Kingdom > .... > Genus > Specie
.

There are taxonomies that cluster symptoms together into diseases to better target them with drugs, investigate the underlying cause, and predict their progress.

But the way these taxonomies are designed does not seem immediately obvious, nor does it seem like one of the fundamental questions that their respective fields struggle with.

If I inquire "why is life classified the way it is ?", I think the best steelman of a biologist my mind can come up with will answer something like:


Well, because it evolved (no pun intended) all the way from Aristotle to us. There are some good Schelling points such as "things that fly are different from things that walk, are different from things that crawl, are different from things that swim, are different from things which are immutable and green". Rough outlines were built around those and some ideas (e.g. Kingdom, Species) kinda stuck because they seem obvious. Once we understood evolution and the fossil records we realized that things are a bit more complex and we came up with this idea of phylogenetics, but we decided to work around the existing rank in the hierarchy to calcify their meaning a bit better, then added more ranks once they seemed necessary.
Yes, maybe even viewing it as a hierarchy is rather stupid, since that whole view works for e.g. multicellular eukaryotes that tend to keep slowly adding to their DNA and leave a fossil record but seems kinda silly for bacteria which swap, add and discard DNA like crazy and leave none but the vaguest trace of their existence a few seconds after their cell wall breaks. But it kinda works even for viruses and bacteria if you make a few adjustments.
Yes, there are arbitrary rules we apply, for example, the more foreign a lifeform is to us the more likely we are to use genetics to classify it, and the more often we encounter it the more likely we are to use phenotype.
Yes, maybe forcing kids to memorize these things is school is pointless and arbitrary, and yes I see no particular reason to put this taxonomy on a golden pedestal, but it's the one that everyone uses so you might as well get used to it.

This is a fairly good defense of the taxonomy, all things considered, it's a very similar defense to the one I'd give if someone asked me why it's still relevant to know C or C++.

But it's a defense that leverages the idea that the current taxonomy is fit enough for its purpose, thus there's no reason to change it. However, I fail to see why we consider it to be so. The role of a taxonomy is to dictate discussion, indexing, and thought patterns, this is a rather complex subject and can only be explored via querying individual preferences and observing how individuals using different taxonomies fare against each other in a competitive environment. But if my only option is to use this taxonomy and doing away with the whole edifice in favor of something new is off-limits, then I think it's fair to argue that we have exactly 0 datapoints to suggest this is a good taxonomy.

If the whole reason we use the taxonomy is because "It kinda classifies all life, so it's fit for purpose", that's like saying brainfuck is Turing complete, so it's fit for purpose. An abstraction can be fit for purpose under the most perverse possible definition and still be very bad.

In programming, if I think C is garbage, or, even worst, if I think OO and imperative programming as a whole is rubbish, I can go to one of 1001 university departments, meetups, and companies that use functional languages and patterns.

If I think that even those are rubbish and I specifically want a functional language designed under some niche tenants of a sub-branch of set theory designed by a few mathematicians in the 50s... I can go to Glasgow and find a whole university department dedicated to that one language.

The reason I can point to C and say "this is an ok language" is because I can take i3 and xmonad, look at their code+binary and say "Look, this is a C program compared to a Haskell one, they fulfill the same function and have x,y,z advantage, and disadvantages". That times 1000, means I have some reason to believe C is good, otherwise C programmers would be out of a job because everyone would be writing superior software in Haskell.

But I'm not aware of any department of biology that said: "Hmh, you know what, this life-classification system we have here could be improved a lot, let's redesign it and use the new system to communicate and teach our students to use it". If we had one such department or 100 such departments, we would suddenly have some data points to judge the quality of our current taxonomy.

A dominant abstraction still has a huge home-field advantage. But the reason for experimenting with abstraction is not to get minor improvements (e.g. Python3.7 to Python3.8) but to get paradigm-shifting ones (e.g. C vs Rust). The changes we are looking for should still be visible even in those subpar conditions.

If Firefox used to be kinda slow, and in the last 2 years it's become the fastest browser on all platforms, that starts to hint at "Huh, maybe this Rust thing is good". It's not a certainty, but if we have 100 other such examples than that's much better than nothing.

Conversely, if the university working with {counterfactual-taxonomy-of-life} is suddenly producing a bunch of small molecules that help people stay thin without significant side effects, although billions of dollars went into researching them and nobody really found one before, maybe that's a hint that {counterfactual-taxonomy-of-life} is bringing some useful thought patterns to the table. It's not a certainty, but if we have 100 other such examples than that's better than nothing.

Granted, I don't expect fundamental taxonomies to be a good candidate for this approach, they are just an easy and uncontroversial example to give. Everyone agrees they are somewhat arbitrary, everyone agrees that we could create better ones but the coordination problem of getting them adopted is not worth solving.

So fine, let me instead jump ship to the most extreme possible example.

Why do we have to use math?

Generally speaking, I can't remember myself or anyone else as kids protesting against learning numbers and how to add and subtract them. As in, nobody asked "Why do we have to learn this?" or "Is this useful to adults?".

Granted, that might be because children learning numbers have just mustered basic speech and bladder control a few birthdays ago, so maybe there's still a gap to be crossed until they can protests to their teachers with those kinds of questions.

But I doubt it. I think there's something almost intuitive about numbers, additions, and Euclidean geometry. Maybe one doesn't come up with them on their own in the state of nature, but they are very intuitive abstractions, once someone points them out to you they seem obvious, natural, true.

This is a famous argument and I think Plato does better justice to it than I could.

Some context, Socrates (So) is arguing with Menos about the existence of "recollection" (I'd rather think of this as abstractions/ideas that become immediately obvious to anyone once pointed out). He brings out a slave with no knowledge of geometry and draws the following figures:

http://cgal-discuss.949826.n4.nabble.com/file/n2015843/image.jpg

  • So: Tell me, boy, do you know that a square is like this?
  • Slave: I do.
  • So: And so a square has these lines, four of them, all equal?
  • Slave: Of course.
  • So: And these ones going through the center are also equal?
  • Slave: Yes.
  • So: And so there would be larger and smaller versions of this area?
  • Slave: Certainly.
  • So: Now, if this side were two feet and this side two feet also, how many feet would the whole be? Look at it like this: if this one were two feet but this one only one foot, wouldn't the area have to be two feet taken once?
  • Slave: Yes.
  • So: When this one is also two feet, there would be twice two?
  • Slave: There would.
  • So: An area of twice two feet?
  • Slave: Yes.
  • So: How much is twice two feet? Calculate and tell me.
  • Slave: Four, Socrates.
  • So: Couldn't there be one different from this, doubled, but of the same kind, with all the lines equal, as in that one?
  • Slave: Yes.
  • So: And how many feet in area?
  • Slave: Eight.
  • So: Come then, try to tell me how long each line of this one will be. In that one, it's two, but what about in that doubled one?
  • Slave: It's clearly double, Socrates.
  • So: You see, Meno, that I am not teaching anything, but put everything as a question. He now believes he knows what sort of line the eight feet area comes from. Or don't you think so?

The point at which children start questioning their math teachers seem to coincide with the point where more complex abstraction is introduced.

There's nothing fundamentally "truer" about euclidian geometry than about analysis. Yes, the idea of breaking down lines into an infinity of infinitely small distances might conflict with the epistemology of a kid, but so might the axioms of Euclidian geometry.

Where the difference between Euclidian geometry and analysis lies is in the obviousness of the abstraction. With something like analysis it seems like the abstractions being thought are kind of arbitrary, not in that they are untrue, but in that they could be differently true.

Maybe it's not even obvious why "infinitely small distance" is a better choice of abstraction than "100,000,000,000 small distances".

It's not obvious why reasoning analytically about the area under a curve is superior to the Greek geometric approach of starting with a few priors and reasoning out equality through similarity. (not to a kid, that is)

It's not obvious why the 'trend' of a certain single-parameter function, represented by another single-parameter function is an important abstraction to have at all.

I think that kids asking their math teachers "Why do we have to learn this?", want, or at least would be best served with an answer to one of two interpretations:

  1. Why is this abstraction more relevant than any other abstraction I could be learning? The abstractions math previously gave me seemed like obvious things about the world. This analysis thing seems counter-intuitive at first, so even if it's true, that in itself doesn't seem like reason enough for me to care.
  2. Why was this abstraction chosen to solve this set of problems? How did people stumble upon those problems and decide they were worth solving? What other abstractions did they try to end up with on that is so complex?

But instead, the answers most teachers give are answers to the question:

Why do we have to learn math?

I think most people have this mental split at some point, between the mathematic that is intuitive and that which isn't. Maybe for some people, it happens right after they learn to count, maybe for others, it happens when they get to 4d geometry.

I think many people blame this split on something like curiosity, or inborn ability. But I blame this split on whichever qualia dictate which mathematical abstractions are "intuitive" and which aren't.

Furthermore, I don't think this split can be easily resolved, I think to truly resolve it you'd need to find a problem impervious to intuitive abstractions, then try out a bunch of abstractions that fail short of solving it, then reason your way to one that does (which is likely going to be the "standard" one).

But it seems that abstraction-finding, whilst most certainly a part of mathematics, is something almost nobody is explicitly taught how to do.

To put it another way, I think that anyone learning to program, if asked "How would you redesign C to make it better?", could give an answer. Maybe a wrong answer, almost certainly an answer far worst than the "best" answers out there. Most people are asked some variant of this question, or at least ask themselves, a significant percentage even try to implement it... maybe not quite at the level of trying to redesign C, but at least at the level of trying to redesign some tiny library.

On the other hand, someone that's learned analysis for a few years, if asked how they would improve it, would fail to answer... even a poor answer, even a wrong answer, the question would seem as intractable to them as it would be to their 6-year-old self.

If I proposed to you that in 20 years schools and colleges would be teaching either Rust or Python instead of C and Java you might argue with that idea, but it would certainly seem like something within the realm of real possibilities.

If I proposed to you that in 20 years schools and colleges would have thrown away their analysis books and started teaching a very different paradigm you would ask me what's the stake and odds I'm willing to bet on that.

Maybe that is because math is perfect, or at least because math is close to perfect. Maybe one can make minute improvements and completions to the old knowledge, but the emphasis in that sentence should be placed on "minute" and "completions".

One thing that strikes me as interesting about mathematics, under this hypothesis, is that it seems to have gotten it impossibly right the first time around. E.g. the way one best abstracts figuring out the equation for the area under a curve in 17th-century with limited ink and paper, is the same way one best abstracts it when sitting at a desk with a computing machine millions of times faster than our brain.

I'm not comfortable making this point about analysis, I've tried thinking about an idea like "What if we assumed continuous variables did not exist and built math from there Pythagora style", every time I ran into an issue, so I'm fairly sure a good mathematician could poke 1001 holes in this approach.

However, in areas that interest me like statistics, I think it's fairly easy to see gralingly bad abstractions that have little reason for existing. From people still writing about trends without using any test data, let alone something like k-fold cross-validation, to people assuming reality has an affinity for straight lines and bell shapes until proven otherwise.

Maybe statistics is alone in using outdated abstractions, or maybe there are many areas of math like it. But because mathematics is (fairly) hierarchical in terms of the abstractions it uses, there's no marketplace for them to fight it out. New abstractions are forced to be born into new niches, or via strangling out a competitor by proving an edge case they couldn't.

When Python was born nobody ever claimed it does more than C, it is, by definition, impossible to do something with Python (as implemented by CPython) that can't be done with C. On the other hand, that doesn't make the Python abstraction inferior, indeed, for the vast majority of jobs, it's much better.

Is there such an abstraction we are missing out on in math? Some way to teach kids analysis that is as obvious as Euclidian geometry. I don't know, but I do know that I'd have no incentive to ever figure it out and I don't think anybody else does either. That fact makes me uncomfortable.

Perhaps mathematics is the worst possible field to reason about abstraction quality, but I feel like there are a lot of other easier picks where even a bit of abstraction competition could greatly improve things.

Alas

I think the way programming handles creating new abstractions is rather unique among any field of intellectual endeavor.

Maybe this is unique to programming for a reason or maybe I'm wrongfully associating the most fluid parts of programming with the most immutable parts of other fields.

But I do think that the idea is worth exploring more, especially light of our knowledge accumulation problem and the severe anti-intellectualism and lack of polymaths in the current world.

Maybe all theory is almost perfect and improving it can only be done incrementally. But maybe, if thousands of people attempted to completely revamp various theories every day, we'd come up with some exponentially better ones. I think the only field that provides evidence regarding this is programming and I think the evidence points towards the latter approach is very promising.

24

17 comments, sorted by Highlighting new comments since Today at 1:39 PM
New Comment

There is a major difference between programming and math/science with respect to abstraction: in programming, we don't just get to choose the abstraction, we get to design the system to match that abstraction. In math and the sciences, we don't get to choose the structure of the underlying system; the only choice we have is in how to model it.

Given a fundamental difference that large, we should expect that many intuitions about abstraction-quality in programming will not generalize to math and the sciences, and I think that is the case for the core argument of this post.

The main issue is that reality has structure (especially causal structure), and we don't get to choose that structure. In programming, abstraction is a social convenience to a much greater extent; we can design the systems to match the chosen abstractions. But if we choose a poor abstraction in e.g. physics or biology, we will find that we need to carry around tons of data in order to make accurate predictions. For instance, the abstraction of a "cell" in biology is useful mainly because the inside of the cell is largely isolated from the outside; interaction between the two takes place only through a relatively small number of defined chemical/physical channels. It's like a physical embodiment of function scope; we can make predictions about outside-the-cell behavior without having to track all the details of what happens inside the cell.

To draw a proper analogy between abstraction-choice in biology and programming: imagine that you were performing reverse compilation. You take in assembly code, and attempt to provide equivalent, maximally-human-readable code in some other language. That's basically the right analogy for abstraction-choice in biology.

Picture that, and hopefully it's clear that there are far fewer degrees of freedom in the choice of abstraction, compared to normal programming problems. That's why people in math/science don't experiment with alternative abstractions very often compared to programming: there just aren't that many options which make any sense at all. That's not to say that progress isn't made from time to time; Feynman's formulation of quantum mechanics was a big step forward. But there's not a whole continuum of similarly-decent formulations of quantum mechanics like there is a continuum of similarly-decent programming languages; the abstraction choice is much more constrained.

There is a major difference between programming and math/science with respect to abstraction: in programming, we don't just get to choose the abstraction, we get to design the system to match that abstraction. In math and the sciences, we don't get to choose the structure of the underlying system; the only choice we have is in how to model it.

The way I'd choose to think about it is more like:

1. Language, libraries ...etc are abstractions under an underlying system (some sort of imperfect Turing machine), that programmers don't have much control over

2. Code is an abstraction over a real world problem meant to regorize-it to the point where it can be executed by a computer (much like math in e.g. physics is an abstraction meant to do... exactly the same thing, nowadays)

Granted, what the "immutable reality" and the "abstraction" are depends on who's view you take.

The main issue is that reality has structure (especially causal structure), and we don't get to choose that structure.

Again, I think we do get to chose structure. If your requirement is e.g. building a search engine and one of the abstractions you chose is "the bit that stores all the data for fast querying", because that more or less interacts with the rest only through a few well defined channels, then that is exactly like your cell biology analogy, for example.

To draw a proper analogy between abstraction-choice in biology and programming: imagine that you were performing reverse compilation. You take in assembly code, and attempt to provide equivalent, maximally-human-readable code in some other language. That's basically the right analogy for abstraction-choice in biology.

Ok, granted, but programmers literally write abstractions to do just that when they write code for reverse engineering... and as far as I'm aware the abstractions we have work quite well for it and people doing reverse engineering have the same abstraction-choosing and creating rules every other programmer has.

Picture that, and hopefully it's clear that there are far fewer degrees of freedom in the choice of abstraction, compared to normal programming problems. That's why people in math/science don't experiment with alternative abstractions very often compared to programming: there just aren't that many options which make any sense at all. That's not to say that progress isn't made from time to time; Feynman's formulation of quantum mechanics was a big step forward. But there's not a whole continuum of similarly-decent formulations of quantum mechanics like there is a continuum of similarly-decent programming languages; the abstraction choice is much more constrained

I mean, this is what the problem boils down to at the end of the day, nr of degrees of freedom you have to work with, but the fact that sciences have few of them seems non obvious to me.

Again, keep in mind that programmers also work within constraints, sometimes very very very tight constraints, e.g. a banking software's requirements are much stricter (if simpler) than those of a theory that explains RNA Polymerase binding affinity to various sites.

It seems that you are trying to imply there's something fundamentally different between the degrees of freedom in programming and those in science, but I'm not sure I can quite make it out from your comment.

Let me try another explanation.

The main point is: given a system, we don't actually have that many degrees of freedom in what abstractions to use in order to reason about the system. That's a core component of my research: the underlying structure of a system forces certain abstraction-choices; choosing other abstractions would force us to carry around lots of extra data.

However, if we have the opportunity to design a system, then we can choose what abstraction we want and then choose the system structure to match that abstraction. The number of degrees of freedom expands dramatically.

In programming, we get to design very large chunks of the system; in math and the sciences, less so. It's not a hard dividing line - there are design problems in the sciences and there are problem constraints in programming - but it's still a major difference.

In general, we should expect that looking for better abstractions is much more relevant to design problems, simply because the possibility space is so much larger. For problems where the system structure is given, the structure itself dictates the abstraction choice. People do still screw up and pick "wrong" abstractions for a given system, but since the space of choices is relatively small, it takes a lot less exploration to converge to pretty good choices over time.

Alright, I think what you're saying make more sense, and I think in principle I agree if you don't claim the existence of a clear division between , let's call them design problems and descriptive problems.

However it seems to me that you are partially basing this hypothesis on science being more unified than it seems to me.

I.e. if the task of physicists was to design an abstraction that fully explained the world, then I would indeed understand how that's different from designing an abstraction that is meant to work very well for a niche set of problems such as parsing ASTs or creating encryption algorithms (aka things for which there exists specialized language and libraries).

However, it seems to me like, in practice, scientific theory is not at all unified and the few parts of it that are unified are the ones that tend to be "wrong" at a closer look and just serve as an entry point into the more "correct" and complex theories that can be used to solve relevant problems.

So if e.g. there was one theory to explain interactions in the nucleus and it was consistent with the rest of physics I would agree that maybe it's hard to come up with another one. If there's 5 different theories and all of them are designed for explaining specific cases and have fuzzy boundaries where they break and they kinda make sense in the wider context if you squint a bit but not that much... then that feels much closer to the way programming tools are. To me it seems like physics is much closer to the second scenario, but I'm not a physicist, so I don't know.

Even more so, it seems that scientific theory, much like programming abstraction, is often constrained by things such as speed. I.e. a theory can be "correct" but if the computations are too complex to make (e.g. trying to simulate macromolecules using elementary-particle based simulations) than the theory is not considered for a certain set of problems. This is very similar to e.g. not using Haskell for a certain library (e.g. one that is meant to simulate elementary-particle based physics and thus requires very fast computations), even though in theory Haskell could produce simpler and easier to validate (read: with fewer bugs) code than using Fortran or C.

Cell happens to be a fairly straightforward abstraction in biology. If you however more a bit further out to concepts like muscle things become less clear.

A layperson might think that a muscle is a unit that can be activated as one unit. That's not true and it's possible to activate parts of a muscle. The unit of a muscle comes from what makes sense for surgeons to cut with knifes. It's quite possible that in many applications where you don't cut people apart with knifes you could find a better abstraction.

After ICD-10 added important classifications such as W59.22 Struck by turtle our main ontology for illnesses, the ICD-11 just added SG29 Triple energizer meridian pattern and SF57 Liver qi stagnation pattern I think it's clear that there are many possible ways to model reality.

I don't completely agree with your characterisation "[math] seems to have gotten it impossibly right the first time around" of how we got the current abstractions in mathematics. Taking your example of analysis, 1) Leibniz and Newton put forward different ideas about what the operation of taking a derivative meant, with different notations 2) there was a debate over (two) centuries before the current abstractions were settled on (the ones that are taught in undergraduate calculus) 3) in the 60s famously "non-standard analysis" was developed, to give an example of a radical departure, but it hasn't really caught on.

Still within analysis, I would point out that it's common(-ish?) to teach two theories of integration in undergraduate math: Riemann and Lebesgue. Riemann integration is the more intuitive "area of thin rectangles under the curve" and is taught first. However, the Lebesgue integral has better theoretical properties which is useful in, for example, differential equations. And beyond undergraduate, there are conceptions of limits in topology and category theory also.

Overall, I'd agree that the rate of trying out new abstractions seems to be lower in mathematics than programming, but as another commenter pointed out, it's also much older.

A second point is that the relevant distinction may be teaching mathematics vs research mathematics. It seems to me that a lot more theories are tried out on newer mathematics in topics of active research than in teaching the unwashed hordes of non-math-major students.

I mean, I basically agree with this criticism.

However, my problem isn't that in the literal sense new theories don't exist, my issue is that old theories are so calcified that one can't really do without knowing them.

E.g. if I as a programmer said "Fuck this C nonsense, it's useless in the modern world, maybe some hermits in an Intel lab need to know it, but I can do just fine by using PHP" then they can become Mark Zuckerberg. I don't mean that in the "become rich as *** sense" but in the "become the technical lead of a team developing one of the most complex software products in the world" sense.

Or, if someone doesn't say "fuck C" but says "C seems to complex, I'm going to start with something else" then they can do that and after 5 years of coding in high level languages they have acquired a set of skills that allowed them to dig back down and learn C very quickly.

And you can replace C with any "old" abstraction that people still consider to be useful and PHP with any new abstraction that makes things easier but is arguably more limited in various key areas (Also, I wouldn't even claim PHP is easier than C, PHP is a horrible mess and C is beautiful by comparison, but I think the general consensus is against me here, so I'm giving it as an example).

In mathematics this does not seem to be an option, there's no 2nd year psychology major that decided to take a very simple mathematical abstraction to it's limits and became the technical leader of one of the most elite teams of mathematicians in the world. Even the mere idea of that happening seems silly.

I don't know why that is, maybe it's because, again, math is just harder and there's not 3-month crash course that will basically give you mastery of a huge area of mathematics the same way a 3-month crash course in PHP will give you the tools needed to build proto-facebook (or any other piece of software that defines a communication and information interpretation & rendering protocol between multiple computers).

Mathematics doesn't have useful abstractions that allow the user to be blind to the lower level abstractions, nonstandard analysis exists but good luck trying to learn it if you don't know a more kosher version of analysis already, you can't start at nonstandard analysis... or maybe you can ? But then that means this is a very under-exploited idea and it gets back to the point I was making.

I'm using programming as the bar here since it seems that, from the 40s onward, the requirements to be a good programmer has been severely lowered due to the new abstraction we introduce. In the 40s you had to be a genius to even understand the idea of computer. In modern times you can be a kinda smart but otherwise unimpressive person and create revolutionary software or write an amazing language of library. Somehow, even though the field got more complex, the entry cost went from 20+ years including the study of mathematics, electrical engineering and formal logic to a 3-month bootcamp or like... reading 3 books online. In mathematics it seems that the entry cost gets higher as time progresses and any attempts to lower that are just tiny corrections or simplifications of existing theory.

And lastly, I don't know if there's a process "harming" math's complexity that could easily be stopped, but there are obvious processes harming programming's complexity that seems, at least in principle, stopable. E.g. if you look at things like coroutines vs threads vs processes, which get thought as separate abstractions, yet are basically the same **** thing if you move to all but a few kernels that have some niche ideas about asyncio and memory sharing.

That is to say, I can see a language that says "Screw coroutines vs threads vs processes nonsense, we'll try to auto-detect the best abstraction that the kernel+CPU combination you have supports for this, maybe with some input from the user, and go from there" (I think, at least in part, Go has tried this, but in a very bad fashion, and at least in principle you could write a JVM + JVM language that does this, but the current JVM languages and implementations wouldn't allow for this).

But if that language never comes, and every single programmers learn to think in terms of those 3 different parallelism abstractions and their off-shots, then we've just added some arguably-pointless complexity, that makes sense for our day and age but could well become pointless in a better-designed future.

And at some point you're bound to be stuck with things like that and increase the entry cost, though hopefully other abstractions are simplified to lower it and the equilibrium keeps staying at a pretty low number of hours.

(Also, I wouldn't even claim PHP is easier than C, PHP is a horrible mess and C is beautiful by comparison, but I think the general consensus is against me here, so I'm giving it as an example).

The consensus isn't against you here. PHP consistently ranks as one of the most hated programming languages in general use. I've seen multiple surveys.

You make this comparison between programmers and mathematicians, but perhaps the more apt analogy is programming language designers vs mathematicians and programmers vs engineers/scientists? I would say that most engineers and scientists learn a couple of mathematical models in class and then go off and do stuff in R or Matlab. What the average engineer/scientist can model presently is now far greater than even the very best could model in the past. And they don't need to know which of the 11 methods of approximation is going on under the hood of the program.

Then the different abstractions are things like ODE models, finite element analysis, dynamical systems (eg stability), monte carlo, eigenvalue analysis, graph theory stuff, statistical significance tests, etc

CompSci and Programming: less that 100 years old. Math: over 3000 years old. Let's see if you get to redesign your programming languages in 3000 years.

3000 is a bit of an exaggeration, seeing as the vast majority of mathematics was invented from the 17th century onwards, it's more fair to call it 400 years vs programming's 70-something.

Though, if we consider analogue calculators, e.g. the on leibniz made, then you argue programming is about as old as modern math...but I think that's cheating.

But, well, that's kind of my point. It may be that 400 years calcifies a field, be that math or programming or anything else.

Now, the question remains as to whether this is good or not, intuitively it seems like something bad.

I am not sure if you compare corresponding things in these programming analogies.

In programming, switching from C to Python is simple, switching from object-oriented to purely functional programming is more difficult, and trying an entirely new approach to programming that doesn't use functions and variables at all is hardcore.

Doing biology without talking about cells and evolutionary tree... should perhaps be analogical to programming without functions and variables, rather then programming in a different language... which would perhaps be more like a choice between calling species by Latin or English names.

But the way these taxonomies are designed does not seem immediately obvious, nor does it seem like one of the fundamental questions that their respective fields struggle with.
If I inquire "why is life classified the way it is ?", I think the best steelman of a biologist my mind can come up with will answer something like:

I think that ignores what happened in the last two decades. We do have the OBO Foundry ontologies that follow the explicit framework of Basic Formal Ontology as layed out by Barry Smith et al.

As far as the domain of species go, as we got efficient DNA sequencing we changed our way of classify species to be more centered around DNA.

You seem to have the idea that a programming language should define a certain set of abstractions and that is that. But to many one of the key powers that programming brings is the ability to define and model new abstractions. In addition to your list I also would therefore also require

  • Ability to create powerful abstractions within the language, and
  • Ease of avoiding redundancy/repetition and/or boiler plate code in aid of such abstractions.

When you use abstractions to actually do work, the effeciency matters a lot. Hence programming languages.

When you use them to mentally sort things for general knowledge of what's out there and memory storage like in biology, if it works it works. Kingdoms seem to work for this.

When you use them to mentally sort things for general knowledge of what's out there and memory storage like in biology, if it works it works. Kingdoms seem to work for this.

Could you expand this a bit ?

How often are the kingdom's really used in a lab or with detailed research? I'm guessing not often (I've only done intro to bio myself though I've talked to researchers about there work and the kingdom's never came up).

They might be useful for giving people learning biology a general grasp of the various organisms and some differences, put into large categories.

There might be some times it's useful, maybe as a starting place in comparing different organisms, but it isn't an abstraction that is the base of how the actual field does research.

(As opposed to PLs, where the abstraction is the main tool of the craft)