When Thomas Schelling first worked out his game-theoretic models of segregation, he used coins on a grid to manually demonstrate how micromotives could lead to macrobehaviors — and he recommended against using the primitive computers of the time:
I cannot too strongly urge you to get the nickels and pennies and do it yourself. I can show you an outcome or two. A computer can do it for you a hundred times, testing variations in neighborhoods demands, overall ratios, sizes of neighborhoods, and so forth. But there is nothing like tracing it through for yourself and seeing the process work itself out. It takes about five minutes — no more time than it takes me to describe the result you would get. In an hour you can do it several times and experiment with different rules of behavior, sizes and shapes of boards, and (if you turn some of the coins heads and some tails) subgroups of nickles and pennies that make different demands on the color compositions of their neighborhoods (Schelling 1974, 48).
Later, when computers had advanced enough to give real-time feedback, he changed his mind, learned BASIC, and learned what programming does to the programmer:
First, programming requires a decomposition of a whole that is given before by a more or less intuitive description. Simple components have to be identified and specified. Their interplay, the parameters and their possible values, all that has to be exactly defined in a precise language with a rigorous grammar. Whoever started to program, realises after some lines of coding the ambiguities and the holes in informal descriptions that, beforehand, he or she considered perfectly clear and complete. Programming implies to resolve the ambiguities and to fill the holes. In short: Programming forces the programmer to sharpen his or her view on the subject.
Second, programming has an inherent tendency, if not irresistible seduction, to generalisation: it often transforms the original subject, its features or components, into instances of something much more general.
A first example: In an informal description we may have two groups, blacks and whites. In the program they are represented by two lists. But why to stop with just two. Why not three, four, five … ? Whoever commands the natural numbers, can’t avoid asking that question, and in that moment the idea of a generalised group structure with m groups of possibly different group size is born. Such a generalised view may require not even a single additional line of code, because the original case (blacks and whites only), was technically realised in such a way that, whether two or m groups, is simply a question of just one parameter value in the lines that were already written to cope with two groups. It is a frequent programming experience that code, written to implement a specific feature of the subject matter, unintentionally (!) realises the particular as an instance of a generalisation that goes far beyond the original feature.
Another example: While programming rules of movement, starting from some intuitive descriptions, it becomes obvious that there are much more and totally different possible rules. For instance, rules that require consent of the neighbourhood that someone wants to enter. Almost never can we implement all alternatives. But from now on we know that whatever we implement is just an instance of something more general that might be called a migration regime. Again, programming has changed the view. In short: Programming is an eye opener; by programming — for the most part unintentionally — we get to a more general point of view.