Examples related to DataAndCodeAreTheSameThing.
Example 1
This is a simple real-case example of code and data being interchangeable.
I was to build an HTML report of amounts with an outer category and inner category of accounting items. The inner categories were generally fixed. Originally I made code something like this:
for each outer category { showOuterBandHeader(....) showRow("Labor", "laborAmt", ....) showRow("Parts", "partsTot", ....) showRow("Taxes", "tax", ....) etc.... }The first parameter is the row sub-category title, and the second one is the column name that contains the value source in a database. (This example is not really about databases, I would note. Also, the parameters were not the literal column values that were to be displayed. They just supplied info to differentiate each row.)
Later on I realized that I needed the list of database column names (second parameter) to generate some SQL code in a different spot in the code. Rather than repeat the list of database columns somewhere else (a violation of OnceAndOnlyOnce), I decided to put the above parameters into a data structure rather than as function parameters. (It doesn't really matter whether the structure was a table or something else in this example.) I could then loop/traverse through the structure in both spots of the code that needed such information. (In languages such as LISP the transformation would have been even easier since parameter lists and data lists use the same syntax.) The code area above would then look something like:
for each outer category { showOuterBandHeader(....) for i = each_item_in_struc(theStruc) { showRow(i.title, i.colName, ....) } }The point here is that a structure with data can replace a bunch of function calls, and visa versa.
Has anyone seriously contested this?
I thought they were. That is how I interpreted their complaints against DataAndCodeAreTheSameThing.
I don't agree with Costin, but I doubt this will convince him.
As a potentially unrelated example...
Consider the following code
The FoldFunction will return a single value, essentially folding the list into a single value using the supplied function.
Now, for that function, there is a matching function which when applied to a 'unfold' function, would result in the original list (it is possible that the reverse function would contain an oracle, but this is uninteresting).
Simplifying slightly, let's add a constraint that the initial value shall be nil, null or whatever. In practical terms, this would merely require that the function be special cased; in many domains, there is already conceptually a default value (0 (numbers), null (objects), black (colours)) that would be appropriate for a given function, this could be internalized in the function.
Now we have an identity: (unfold function' null (fold function null (<list>))) == <list> In other words:
and
So, to bring this back on topic, the interesting question is not whether the exchange/conversion is possible. It's trivially true... the function could merely contain the list internally; the list could contain the source for a quine (i.e. a SelfPrintingProgram). The interesting question is can we efficiently go both directions? Or is there a static, most efficient form for any given piece of data? Do the forms for all data tend to lean in one or another direction, towards or away from code? Effectively, it's a question of compression.
And, to bring this to personal opinion, this is where the two sides start simply talking past each other. Relational is a technique of managing data. In whatever form it comes. One can apply relational calculus to any data constrained appropriately, regardless of its encoding. Is it not possible that the simplest most efficient manner to encode a single piece of data is through an object which encodes it through functionality? Likewise, one can apply functionality to relations and domains, to avoid describing what is technically a set of distinct values, but which may be more convenient to work with as a set of functionality.
There is work being done in both directions. TableOrientedProgramming is a recognition that OO is onto something, even if some implementation details are wacko (hierarchical management, etc). Extensions which allow relational set operations on sets of objects are a recognition that relational is onto something, even if the seeming lack of a model of computation proves annoying.
And, on that note, I resign myself to the fact that I don't know what I'm talking about :)
-- WilliamUnderwood (a disinterested third party)
Nice... I'm not quite sure what yet, but I'm sure that gave me something to think about!
These seems to come back to an argument(s) issue of which is more "convenient". We lack anything near objective metrics of "convenience". We are right back to the old metrics of code size and change impact analysis. I suspect it all boils down to which one best fits one's way of thinking. DataCentricThinking.