Yesterday, I had a realization about boilerplate code.
It seems like there are certain tasks (writing a compiler, writing a graphics pipeline) which involve rewriting a lot of code that is very well understood. So why can't this just go into a library? Why does it take a thousand lines of code just to get a triangle on the screen, or to write a basic bidirectional elaborator?
It is because the *surface area of customization* is very large, and it's far easier to customize code that you have written than it is to expose exactly the right options in a library. There are just so many choices to make, and all of them make sense in *some* scenarios, that it doesn't make sense to abstract. The user of an abstraction library would need to effectively give the library as much information as it would take to simply write it yourself.
An abstraction layer is going to have to make some strong assumptions about what you want.
For instance, you could use a game engine, or you could use Racket and avoid writing a parser at all. But these aren't exposing the underlying API in a concise way, they are writing lots of algorithms that use the underlying API in particular patterns, patterns which you may or may not want.
So I think I've gotten over my aversion towards boilerplate. I now think of boilerplate not as "a tax I have to pay in order to do something I care about" and rather as "a visual representation of the space of decisions I can make about the thing I'm working on." Which is cool!
Viva la boilerplate!