I’ve been recently playing with Scheme, reading R⁷RS and so on and I found something really interesting: Even with its high level of abstraction, it doesn’t hide the complexity and makes you pay attention to it.
That’s extremely powerful and interesting.
It’s even more interesting if you think about the fact that Scheme can be implemented from scratch in an acceptable amount of time by a couple of hands. You don’t need to be a big corporation or a big group of developers coding for years to implement it.
It’s simple but it doesn’t hide the complexity of the implementation. That’s a really powerful balance.
But both points are too much to leave them here without playing with them separately so let’s try to understand why both of the points are1 fundamental.
Hidden Latent complexity
You can create the best programming language in the world but the complexity of the programming can’t be eliminated because the user of the language will be, actually, programming. So, you can take two approaches here:
- Expose the intrinsic complexity of programming.
- Make it look as complexity doesn’t exist. Which means hiding the complexity as much as you can under layers of abstraction.
Most of modern programming languages go for the second option. But not only programming languages, also operating systems, computers themselves and many areas more. Which is not specially bad in general, but it’s dangerous when you need control.
Most of the times where complexity is hidden by design, it’s just latent complexity. It’s harder to reach by the user, so the user scope of things they can do is reduced (and with it the their ability to decide with a high level of detail) but the complexity is still there, happening without being noticed, under the surface and being impossible to correct if something goes wrong.
Think about your cellphone. You can’t open it, change the battery, change it’s software, change… anything. Because it’s hard to do and “people don’t need to know about that“. But finally, what you have is a phone that is impossible to repair if something goes wrong or impossible to change if you want it to do something that is not the default behaviour.
It is a problem (some people is fixing trying to fix, by the way) but it’s not a problem for everyone because everyone doesn’t need to have that level of complexity exposed. But they should have the right to see it if they wanted to.
As engineers working on technology, we should be demanding for the complexity of things being exposed, more than running away from it.
As engineers we are supposed to want to know how stuff works!
In the case of programming languages, I want to control what the program does and I be aware of what I’m doing and which decisions I’m taking.
When complexity is exposed you are reminded of the importance of every choice you make. It’s not something that happens: you have to think about it.
In Scheme: List vs Vectors. Which one is better? Why have both? Why not use use one all the time?
It’s reminding you what do you have under the hood, even if you aren’t implementing it yourself. That way you don’t forget about your job.
Simplicity means that there’s no unneeded complexity. It doesn’t mean that complexity is hidden. We tend to confuse both terms too often.
Scheme is simple, because its core is small and it’s based in few concepts. Being simple means that concepts are clear and consistent and have few or none exceptions.
In many platforms abstraction layers are added until the internals are hidden or blurred. In this case, complexity is directly hidden by implementation, more than by users themselves running away from it.
Some would ask: “Who cares about the details?” 3 And it’s perfectly fine to think that at some point but when it comes to choosing the right tool to the right problem, performance and fine tunning, you’d really like to know how they are implemented because implementation is what makes some operations be faster or more accurate than others. And, probably more important than that, being aware about how stuff is implemented make us independent enough to change the implementation if we want, which is the base of free software.
When your tools hide reality from you for long enough, you start to forget that the reality still exists even if you are not watching it and you start acting like it wasn’t there.
Assembly then… Right?
Don’t get me wrong. I’m not against simplification or making our job easier. Scheme, is a really high-level language. Abstraction is good.
Accidental self-lobotomy is not that good.
This blogpost was triggered by this talk where a musician talks about chiptune music and says how making chiptune music made him a better guitarist. It has some good points about constraints and complexity.