Part 1
Last time I alluded to the most important aspect of knowledge structure: some structures are more or less resistant to being changed to have some other function (denotation). Additionally, whether a structure is easy to change to some new problem is not simply a matter of luck. Rather, some structures are better than others, because they contain more knowledge. Now I will give some illustrations.
First, let's reexamine the multiply function. What if the situation changed and we suddenly had to rewrite our multiply function with a special constraint? Such as, what if the built-in multiplication function in our programming language was no longer available? Or what if user-defined function calls suddenly became very slow and expensive? Or what if there was a problem with assignment, and we couldn't use that (basically, no equal sign allowed).
It turns out each of these problems would break one of the multiply functions so badly we would be better off starting over from scratch than trying to salvage it, and the other two wouldn't need even a single change. (If you're wondering, no built-in multiplication ruins the third multiply; no assignment ruins the iterative version; and user-defined function calls being expensive ruins the recursive version.) This demonstrates that structure makes a difference. But so far none are obviously better than others.
Next, lets imagine we were writing a program that played some game, and a few dozen times in the program we needed to refer to the number of actions each player gets per turn. And lets suppose it's 8 now, but possible this may change in future versions of the game. One thing we could do is everywhere we need to refer to the number of actions per turn, put an 8. The program will run just fine. But if we have to change the number of actions per turn later (or perhaps we'd just like to try out a different number to see how it works, to see if changing it might be a good idea at all), then we will have to go through our whole program and alter a few dozen lines of code! That's a pain, and there's a better way.
What we should do is define a constant variable, int ACTIONS_PER_TURN = 8
, and then write ACTIONS_PER_TURN
instead of 8 throughout our program. Then, we could very easily change the number of actions per turn by altering a single line of code. This new program using a constant variable has exactly the same denotation as the original one with 8 everywhere -- someone playing the game will never know the difference. But not only is the structure different using a constant variable, it's better because it allows significant advantages in ways it can be changed, with no disadvantage at all(1). One way to put the difference is it contains the knowledge that each of the dozens of 8's in the program is really the same thing, thus allowing them to be changed as a group.
Another example of trying to change a program, is if we had our multiply programs and wanted to do exponentiation (assume there is no built-in function for that). In that case, the program that relied on built-in multiplication is absolutely useless. Just as it would be useless to change to anything at all that wasn't built in. This reveals its structure has very little knowledge in it. On the other hand, the recursive and iterative multiply programs could both be changed to do exponentiation fairly easily. They could also be altered to do a host of other things, because each has a knowledge-laden structure. In effect, they are both set up to do work (in a certain way), and only need to be told what type. (It's not clear which one has more structural knowledge. I believe the recursive one does, but they are useful in different ways.)
So, to sum up, if we wish to change a program to do something else, depending on its structure, we may have an easy time of it, or may be totally out of luck. And furthermore, some structures are better than others, because they contain more knowledge.
(1) It will run negligibly slower, or compile negligibly slower in a compiled language. And I mean negligibly.
PS I understand that if you knew that, for what you were doing, certain structural knowledge was entirely unnecessary, and never would be useful, you might intentionally leave it out, and say this was a better design. However this is very rare on anything but the most trivial project, and does not ruin the idea of better structures. It's just like, if I was trying to learn physics, I might not need an economics lecture. But we can still say economics has useful, true knowledge, and that there is better and worse economic knowledge.
To be clearer, the objection I fear goes, "Constants are nice, if you're going to change them, but if you aren't, using them is a waste of time, therefore which structure is better depends entirely on the problem at hand, and thus better is only a relative term for knowledge structures." This is wrong. It is equivalent to saying, "The laws of supply and demand are nice, if you're learning about economics, but if you aren't, learning them is a waste of time, therefore whether hearing the laws of supply and demand or nothing is better depends entirely on the problem at hand, and thus better is only a relative term for economic theories." In both cases the 'and thus' clause simply does not follow. Just because we might not want a bit of knowledge this instant does not make it equivalent to no knowledge, or make its value relative.
PPS Mad props to David Deutsch, 'cause he's cool.