6 ms·
Sounds like mathematicians defining their assumptions - it's up to them where they draw the line as to what they will work on themselves, and what they'll accep
by 6ren 15y ago
Sounds like mathematicians defining their assumptions - it's up to them where they draw the line as to what they will work on themselves, and what they'll accept as a given. i.e. it's arbitrary.
Taking it back to turing machines, you can simulate any specific design/implementation of a turing machine on some another turing machine, given a program of constant size (an emulator for the first machine). This can be applied to turing machines which include libraries of arbitrary size. So again, it's up to you where you draw the line.
I wonder if the confusion is to do with why you want to draw the line?
I doubt these answers will satisfy, because I'm not clear on your question. I find such questions easier to answer if I get clear on the purpose - why exactly do I want to know how complex a program is? If it's purely out of curiosity, what is the nature of that curiosity? Complexity, from what point of view? how am I thinking about it? What am I worried/concerned about?
BTW: I was going to use "amortized", but it seems specific to over time (an online dictionary supports this). But it does feel correct - is it a legitimate generalization?
EDIT I really think my first answer was best, so I'll flesh it out a little. I understand your question as being, when we measure the length of a program, we can factor some of out into a library routine, to make it shorter. But isn't this shifting things around just cheating? If it simply was cheating, then I don't think you'd have any question about it. I think the puzzle is that it does seem legitimate, in some way, yet also seems like cheating.
My answer is that instead of measuring the length of your program, you measure the aggregate length of all the programs on your computer. From the perspective of this larger system, if that part that was factored into a library was also used by other programs, then it would make the total length shorter. The "clean abstraction" isn't an important consideration in itself, but comes into it only because that's the (a?) way to make it reusable; and being reused is crucial for factoring a component out into a library, to decrease the total length of all programs.
[ One could generalize beyond "all the programs on your computer" all possible programs, weighted by their probability. The probability captures the usefulness of the programs (there's many more nonsense programs than useful ones in the set of all possible programs). This is important, because a uniform probability density wouldn't enable factoring out to make the total shorter - you need some regularity/redundancy for that, which requires some unevenness. Typically, programs do have commonalities because the programs they solve have commonalities. ]
Basically, taking the widest view, would factoring this aspect out make the total system shorter?
I think this explains the sense that factoring out some code into a library does make it shorter, even though when looking at that program in isolation it's just moving things around.
- gruseom 15y agoHere's why I'm interested. The most important thing in making good software is to eschew unnecessary complexity. A program's size is the best measure of its complexity. Therefore we should try to write shorter programs. Much, much shorter programs. (See Alan Kay's VPRI project etc. etc.) It's easy enough to measure the size of a program: LOC or something like it. But how do we define what a program is? Surprisingly, that's not obvious. As you say, how one carves it up seems arbitrary. The conclusion you came to is also one I've come to: you end up having to measure the total size of all the code that's running. But that seems absurd. (Unless you're a Forth person.) It means I can't measure my program's size without measuring, say, Linux's. So to stave off the apparently absurd, we need a simple way to distinguish programs or systems from one another. That's my question. If A and B both call each other, surely they are part of the same system. But what if A calls B, but B doesn't know about A? Does that make them separate? Sometimes one would say yes, for example if B is Linux. Can we always say yes? That would be convenient. But there are lots of such As and Bs in any complex program. That doesn't mean there are lots of programs. I wonder if like so many other things in programming, this is in the end a social question and not a technical one. That's the trouble with referring to "reuse": it depends on how many people know about B and like it well enough to use it. It seems weird to say that A (or the system it belongs to) gets less complex depending on how many other programs use B. That would mean that a system's codebase could get more or less complex without a line of its code actually changing. Again - not an impossible view, but seems absurd. I'm looking for a principle here because this way of thinking about complexity is a big part of how I work and because I want to have an entire company that thinks this way.
- 6ren 15y agoI think my bracketed aside covers this: by using a probability density, it's not affected by how many people are actually using it, or whether that changes. Of course, it's only a conceptual help, since you can't actually know this density: it amounts to knowing all possible tasks now and in future (a practical impossibility) and also knowing all the solutions (a theoretical impossibility). It wraps all that up in two words. I think defining whether A and B are part of the same program is a red herring. If you think of their calls to each other taking place through an interface, they don't need to know about each other - they just expect something that fulfills the contract of the interface. Again, it's like a mathematician arbitrarily making assumptions: we'll take a component that does this as a given. So, A and B aren't part of the same program. They aren't related at all (except that each happens to fulfill some interfaces needed by the other). This perspective is similar to taking probability density, in that it replaces a concrete actual program with an abstract representation. But how then does one measure complexity? My view is you can't, in practice. But we can have a concept that can guide us. Of course, when staying entirely within a single program it's clear that we should factor out commonalities to reduce length. But what about factoring those things out into libraries? I think an approach that works is to think about being in the business of selling those libraries - but not with the perspective of making money for yourself, but for improving the world. [again, this is an abstract concept, so we don't actually need to sell them and can ignore the real-world issue of marketing] So, there's questions like: is there a need for this, in many programs? Can it be reused generally? (or is it specific to program A - shades of Brooks program-vs-product here) Is it a clean abstraction (i.e. can it be used without knowing its details - this reduces complexity in the code that uses it). How much effort/LoC is saved by it? Factoring out code into a library that is broadly needed, is simple to use, saves a lot of code, is simple to use (doesn't require lots of code to use; solution doesn't create more problems - not the cure is worse than the disease) would be needed broadly. Good libraries save the world! I agree that in practice, it becomes a social (or community) issue, and whether it's adopted is important. You might have a great product that no one ever uses; or a crappy one that everyone does. It's messy, in that it's affected by non-programming issues like the particular alternatives existing at this moment, the need for it at this moment. [But again, a probability density circumvents all this] Maybe it's a bit like whether the scientific method requires the communication of the results: you haven't done "science" until you tell someone. It also seems absurd - how can communication affect what you've already done? - but if you being with science being a community effort (like language, commerce and law), then it does make sense: you can't do science alone. And our established science was a community effort (notwithstanding that we wouldn't know of the other stuff). This is contentious - I mention it because it seems like a similar contention. Finally, some caveats. Though I think complexity is central (Occam's razor) and even did a masters around it, it's not everything. For example, in English communication, redundancy helps by giving listeners a way to verify understanding, and different perspectives in case they didn't grasp it, or if the message was ambiguous and the speaker didn't realize it. and raw repetition in case they weren't listening or the message was corrupted/obscured. Some of these were significant in Shannon's original work on information theory. In communication in general, a constant background helps convey a changing foreground - as simple as the lines on a page of printed text; or looking at a file that is laid out neatly, so you can quickly orient yourself, and also notice irregularities. In code, some repetitive concrete structure can be helpful to the humans reading it. Related to this is the concept of "accidental redundancy". This is when two pieces of code are identical, so you factor them out - but it turns out that they change on independent bases, and it was just a coincidence that they happened to appear identical syntactically. i.e. their meaning was different. You can't tell this just by looking at the code, nor by measuring the length. You have to understand the model beneath the code, and even more importantly, understand the problem being solved (though there might be no way to know the two things differ, until they do differ). My over-idealization of short code eventually made me see the benefits of seemingly over-concrete representations. :-) But short code is still central for me, as it seems to be in scientific discovery. The simpler hypothesis/code is likely closer to the truth. And it's happened to me many times that simpler code generalizes in just the right way - before I realized that it would need to generalize that way. :-) Also, the Dirac/antimatter story is nice on this point: http://arachnoid.com/is_math_a_science/index.html http://arachnoid.com/is_math_a_science/index.html (near the end)