Tuesday, November 13, 2012

The Object-Function Paradox.

Previously, I discussed using inheritance to simplify the writing of generic functions. However, it occurred to me that I can't find anyone else advocating the same thing. No one has yet told me it's a bad practice, but I can't find any other examples of it on the web. (If anyone knows of one, please relieve me of my ignorance.) It's a very short amount of code. Obvious and intuitive. So what impedes people from thinking of it? For that matter, why do some have difficulties comprehending it?

C++ programmers seem to think of functions as something very distinct from objects and types, so obviously the OOP principles of code reuse don't apply. Indeed, the standard says in the first sentence under "The C++ Object Model" (1.8)

The constructs in a C++ program create, destroy, refer to, access, and manipulate objects. An object is a region of storage. [ Note: A function is not an object, regardless of whether or not it occupies storage in the way that objects do. — end note ]
This is technically correct. Functions cannot be objects, they're more like a lexical representation of a code section. The problem is that objects can look like functions, but if we think of this object as a function, then we contradict ourselves because functions cannot be objects.

The distinction is not so transparent. We can make objects that look, talk, and feel like functions, but they aren't.

So, when working out a problem, if a programmer notices a repetitious pattern, s/he might say "I'll create another function that executes the common code!" However, the repetition moves from the in-lined pattern to the calling convention. Because this programmer believes functions are not objects, the solution of using inheritance is impossible to cogitate. Because of this fallacy, this programmer may find the solution hard to comprehend.

We end up with this train of thought: Objects can be functions, but functions cannot be objects, and therefore objects are not functions.

What does a function do? It executes some arbitrary code, taking in arbitrary parameters and returning some value. Function-objects do just that! So objects can be functions! But functions aren't objects...

Paradoxes stunt innovation by preventing the problem from being worked out in a logical way. One cannot conceive of how to use OOP-features to implement functions if they believe the two are fundamentally different and incompatible.

Take Zeno's famous paradox. At one time, we all believe "all is one". We thought of things as wholes. Zeno seemed to think that odd and pointed out that one can go half way from A to B, and then half way to B from there, but he would never get to B. This is obviously true, but with the assumption that "all is one", we have to think about how, then, can we never reach B since we should eventually be one away? The invention of calculus gave way for mathematicians to properly reason about infinitesimally small ones, and a whole new field of science opened up. Our first physicist was born.

Russle's Paradox led to several attempts at improving set theory to remove the paradox, such as the invention of Type Theory, which is obviously very important to computer science.

In quantum mechanics, Schrodinger's Cat and Bell's Theorem led to a greater understanding of the field. Even today, many first learn of quantum mechanics through the tale of an alive and dead cat.

If I was more knowledgeable of the histories of math and physics, I might know more examples, but I hope my point has been persuasive: Paradoxical thinking holds us back, as individuals, as a community.

I submit to the reader this: Functions are objects. Objects are functions. A function is not a procedure to call, but the pointer to that procedure, and pointers are objects, or it can be an instantiation of a user-defined type (like ConstructChainable). We should think of C-functions as the fundamentally different and incompatible things. They are low-level. Function objects are first-class citizens.

The hope is that by removing this logical inconsistency in our minds, we can explore areas of possibility that we never imagined. We can invent solutions to problems that before would have caused a cognitive dissonance. We can progress in directions we hadn't realized before. We can really discover something really interesting, but only if we keep an open mind.

1 comment:

  1. "No one has yet told me it's a bad practice" I have found that some of my best and most productive programming comes from things where someone will declare my code a bad practice yet be unable to explain why. My favorite is when Java programmers look at my code base with its 3 or so objects and say (not joking) that for my architecture I should have had closer to 100 objects. Then they notice the structs and lose their minds.
    Personally I have used objects where use the object as its first member variable. I will have to try your object as function as I often have an object that has one core function. Cool.

    ReplyDelete

Please feel free to post any comments, concerns, questions, thoughts and ideas. I am perhaps more interested in what you have to say than you are in what I do.