More on this book
Community
Kindle Notes & Highlights
by
Paul Graham
Read between
June 13 - December 17, 2018
Saying that taste is just personal preference is a good way to prevent disputes. The trouble is, it’s not true. You feel this when you start to design things.
How has your taste changed? When you made mistakes, what caused you to make them? What have other people learned about design?
For architects and designers, it means that beauty should depend on a few carefully chosen structural elements rather than a profusion of superficial ornament. (Ornament is not in itself bad, only when it’s camouflage on insipid form.)
Problems can be improved as well as solutions. In software, an intractable problem can usually be replaced by an equivalent one that’s easy to solve.
I think it’s because humor is related to strength. To have a sense of humor is to be strong: to keep one’s sense of humor is to shrug off misfortunes, and to lose one’s sense of humor is to be wounded by them. And so the mark — or at least the prerogative — of strength is not to take oneself too seriously. The confident will often, like swallows, seem to be making fun of the whole process slightly, as Hitchcock does in his films or Bruegel in his paintings (or Shakespeare, for that matter).
When Bauhaus designers adopted Sullivan’s “form follows function,” what they meant was, form should follow function.1 And if function is hard enough, form is forced to follow it, because there is no effort to spare for error. Wild animals are beautiful because they have hard lives.
I think the greatest masters go on to achieve a kind of selflessness.
At an art school where I once studied, the students wanted most of all to develop a personal style. But if you just try to make good things, you’ll inevitably do it in a distinctive way, just as each person walks in a distinctive way. Michelangelo was not trying to paint like Michelangelo. He was just trying to paint well; he couldn’t help painting like Michelangelo.
The only style worth having is the one you can’t help.
Nothing is more powerful than a community of talented people working on related problems. Genes count for little by comparison: being a genetic Leonardo was not enough to compensate for having been born near Milan instead of Florence.
Intolerance for ugliness is not in itself enough. You have to understand a field well before you develop a good nose for what needs fixing. You have to do your homework. But as you become expert in a field, you’ll start to hear little voices saying, What a hack! There must be a better way. Don’t ignore those voices. Cultivate them. The recipe for great work is: very exacting taste, plus the ability to gratify it.
The more you have to say to get something done, the harder it is to see bugs.
Some hackers prefer the language they’re used to, and dislike anything else. Others say that all languages are the same. The truth is somewhere between these two extremes. Languages do differ, but it’s hard to say for certain which are best. The field is still evolving.
This is just a guess. I may be wrong. My point here is not to diss Java, but to raise the issue of evolutionary trees and get people asking, where on the tree is language x?
Any programming language can be divided into two parts: some set of fundamental operators that play the role of axioms, and the rest of the language, which could in principle be written in terms of these fundamental operators.
It’s important not just that the axioms be well chosen, but that there be few of them. Mathematicians have always felt this way about axioms — the fewer, the better — and I think they’re onto something.
I have a hunch that the main branches of the evolutionary tree pass through the languages that have the smallest, cleanest cores. The more of a language you can write in itself, the better.
So the rate of evolution in programming languages is more like the rate of evolution in mathematical notation than, say, transportation or communications.
As technologies improve, each generation can do things that the previous generation would have considered wasteful. People thirty years ago would be astonished at how casually we make long distance phone calls. People a hundred years ago would be even more astonished that a package would one day travel from Boston to New York via Memphis.
There’s good waste, and bad waste. I’m interested in good waste — the kind where, by spending more, we can get simpler designs. How will we take advantage of the opportunities to waste cycles that we’ll get from new, faster hardware?
I think some of the best programs were essays, in the sense that the authors didn’t know when they started exactly what they were trying to write.
After all, they’re just a subset of hash tables where the keys are vectors of integers.
I don’t predict the demise of object-oriented programming, by the way. Though I don’t think it has much to offer good programmers, except in certain specialized domains, it is irresistible to large organizations. Object-oriented programming offers a sustainable way to write spaghetti code. It lets you accrete programs as a series of patches. Large organizations always tend to develop software this way, and I expect this to be as true in a hundred years as it is today.
Lisp is worth learning for the profound enlightenment experience you will have when you finally get it; that experience will make you a better programmer for the rest of your days, even if you never actually use Lisp itself a lot.
In business, as in war, surprise is worth as much as force.
How can you get anything done in them, I think, without macros?
In Lisp, these programs are called macros. They are programs that write programs.
Ordinarily technology changes fast. But programming languages are different: programming languages are not just technology, but what programmers think in. They’re half technology and half religion.
The pointy-haired boss believes that all programming languages are pretty much equivalent.
So the short explanation of why this 1950s language is not obsolete is that it was not technology but math, and math doesn’t get stale. The right thing to compare Lisp to is not 1950s hardware but the Quick sort algorithm, which was discovered in 1960 and is still the fastest general-purpose sort.
Lisp was a piece of theory that unexpectedly got turned into a programming language.
Expressing the language in its own data structures turns out to be a very powerful feature. Ideas 8 and 9 together mean that you can write programs that write programs. That may sound like a bizarre idea, but it’s an everyday thing in Lisp. The most common way to do it is with something called a macro.
Macros (in the Lisp sense) are still, as far as I know, unique to Lisp. This is partly because in order to have macros you probably have to make your language look as strange as Lisp.
In fact, choosing a more powerful language probably decreases the size of the team you need, because (a) if you use a more powerful language, you probably won’t need as many hackers, and (b) hackers who work in more advanced languages are likely to be smarter.
Code size is important, because the time it takes to write a program depends mostly on its length. If your program would be three times as long in another language, it will take three times as long to write — and you can’t get around this by hiring more people, because beyond a certain size new hires are actually a net lose.
So here we have two pieces of information that I think are very valuable. In fact, I know it from my own experience. Number 1, languages vary in power. Number 2, most managers deliberately ignore this. Between them, these two facts are literally a recipe for making money.