Abstractions - Part1
I think about abstractions a bunch. It comes with the territory of writing code for a living. Software is, after all, just a series of abstractions, translating the written word into instructions for a machine to follow. Examples of software abstractions include type systems, objects and memory models just to name a few.
An abstraction is a set of generalized rules and concepts that target a particular domain. Abstractions are useful because they give us power over the domain that they describe. The whole field of Euclidean geometry was given form by just five axioms that Euclid laid out in his book, the "Elements". Similarly, all general purpose computers today can be wholly derived from the abstract Turing machine as conceptualized by Alan Turing less than a century ago.
Abstractions are everywhere. Take music. Fundamentally, music is simply sound waves propagating through air at different frequencies and amplitudes. But unless you are someone building an automatic speech recognition system, you won't think of music in this way. Instead, we use words like "mellow" or "rad" to describe the bands we like. The more musically refined might use words like "key" or "timbre".
If you look around at anything, then all you see are abstractions. The world is a concept generated by our brains when making sense of the light hitting the sensors in our corneas. It converts the primitives of light at different frequencies and turns them into color, edges and figures.
I went to yellow stone a year ago with a friend and we camped out for a week. My favorite part of that trip was watching the stars at night. It simply boggled my mind to look up at the night sky filled with countless pinpricks of light, each one a star so far that even light had to travel for millions of years to reach us. My mind couldn't comprehend the vastness of the universe - it was too much.
Joseph Stalin is reputed to have said that "the death of one person is a tragedy; the death of one million is a statistic". He then instituted policies that drove up many such "statistics". It is a well studied phenomenon that people tend to become less compassionate as numbers of victims increase. In one such experiment, University of Oregon professor Paul Slovic ran a study on how people responded to tragedies. In one experiment, Slovic asked volunteers in one group if they would help raise money to save eight children who were dying of cancer. Slovic asked another group how much they would raise to save a single cancer patient. Slovic found that people were willing to raise more money for the single cancer patient then the eight. The findings suggested that our ability feel sympathy for people is limited.
If we extrapolate from this result, it seems reasonable to think that our ability to hold anything would be limited given that our minds are of a finite size (this presumes a physical basis for consciousness). British anthropologist Robin Dunbar first made the observation between a primate's brain size and the size of its average social group. By extrapolating out to humans, Dunbar proposed that 150 relationships pushed the cognitive limit of the number of relationships a human brain could comfortably maintain. This number is famously known as Dunbar's number and is also mentioned in Malcom Gladwell's book, "The Tipping Point". In it, Gladwell described the company, W. L. Gore and Associates, that through trial and error discovered that a building with more than 150 people working together would result in social problems and so limited new buildings to 150 people.
Similarly to Dunbar's number, I suspect that there exists a similar cognitive limit for what people can comprehend without resorting to abstractions. An abstraction is tripped in the same manner a circuit breaker would be - when the forces acting upon the mind become too much for the medium to safely process. At this point, abstractions compress away the immense detail into smaller representations of themselves. The thing with compression algorithms though, is that there are always trade-offs and it usually comes at the expense of fidelity.
When programming in higher level programming languages, the ease of writing code is only matched in the inverse by the difficulty of reasoning about the performance of said code. The following is a mistake I commonly see in people who begin programming in python. What's wrong with the following code?
res = "" for s in list_of_strings: res += s
This code takes a list of strings and concatenates all the elements into one long string. Because python strings are immutable, every loop will create a new string with all elements of the string thus far. This would be the equivalent of writing a book and on each additional word, rewriting all the words that have come before. Let's take a look at the proper way to write the above code.
res = "".join(list_of_strings)
This code only creates one string to achieve the same result. The mistake I just described is easy to make because to realize the cost requires knowing about the implementation details of the language at lower levels - the very thing a higher level language "protects" you from in the first place. And so while abstractions are helpful, there lie dragons.
It is dangerous to hold firm to an abstraction without questioning its origins as such actions give birth, not just to performance issues when coding, but also to bigotry and prejudice. Racism is an example of an abstraction taken too far, when an entire class of people is reduced to a collection of stereotypes. Other abstractions to add to this list include climate change denial and terrorism. In each case, believers have formed these abstractions with fundamentally wrong models of the underlying reality and it has led to disastrous outcomes for society.
There is a Heisenberg like uncertainty that happens when we abstract - as we gain more expressive power over the collection, we lose detail on specifics. Despite these trade-offs, the mind must make abstractions for the same reasons we need to build circuit breakers into our electrical systems - to prevent a meltdown. This is especially true today if one's mind is to be sane in the endless cacophony of global information, news and social media. This also makes it especially important to question assumptions and consider things from first principles. Abstractions are useful but we should not be slaves to it. While we think in the abstract, we live in reality. Reality as we know it is constantly changing and so we must change our abstractions of it in turn. In abstract this seems easy to do. In reality, this is always a different.