I propose an example so we can see how TableOrientedProgramming would work in the real world. How about, say, a text editor... which can then be expanded in various ways to become a word processor, if we so feel like it. Hopefully TopMind and the TOP fans will help out, and the OOP fans will try to contribute and learn within the stylistic limits of TOP. Who feels qualified to start us off with a basic design? -- AdamBerger Yea... I'd love to see this... ''I generally don't write editors for a living and thus have insufficient experience to build a worthy TOP text editor at this time. (Although I have considered it in the past as an experiment.) I generally deal with custom business applications for a living and that domain is where I defend TOP. I don't claim it is necessarily a contendor for every domain. -- top'' [I don't write text editors for a living, but I can whip up an example in an hour or two. It doesn't have to be "worthy", just show us how you would use TOP to tackle the problem.] You may want to check out Compiere: http://sourceforge.net/projects/compiere/ It is apparently quite table-driven. For a "toy" example, check out: http://www.geocities.com/tablizer/chal06.htm It would be interesting to see an OO version of the same thing. ---- Myself, I might do something along the lines of : '''Document''' //Table name : ''Position Element'' //Key set : Document.project({Position}).count() == Document.count(); //constraint (table) : '''Content''' : ''Element Text'' : Content.project({Element}).count() == Content.count(); : Document.project({Element}) == Content.project({Element}); //constraint (database) Normal editing of the text would occur by creating a new element and modifying/adding the Position to reference it. The advantage of the separation would be that certain search and replace operations would be trivial. Of course, the more straight forward : '''Document''' : ''Position Character'' : Document.project({Position}).count() == Document.count(); might be more appropriate for both operations anyway: search and replace would be handled by joining the table against itself 'n' times where 'n' is the size of the search; normal editing would occur through reindexing the structure as necessary. Both of these operations would be possible with reasonable efficiency by running differing data structures underneath the table: the same free-block oriented array used in simple text editors could be used, and that particular join could be special cased. In other words, the power comes from the standard manner in which any data structure can be accessed and combined with any other data structure. -- WilliamUnderwood ''What does this line mean?'' : Document.project({Element}).count() == Document.count(); //constraint (table) ''Is "project" used as a noun or a verb?'' It is a constraint, project refers to projection. ''Can you express it in English? I'm unfamiliar with the notation you're using.'' Projecting the table Document down to the keyset {Element} would result in a table containing one key: Position. The trick being that since this is relational, any duplicate values would collapse, and so the only way for a narrowing projection to have the same number of tuples as the original is if the resulting keyset is a candidate key for the original table. The effect is that we have specified a primary key for that table. I'm still unsure how much I want to be primitive in that regard. For example, do I want a specific and special primary key constraint, or is it just as easy to have a function? If the latter, then the whole : .project({}).count() ==
.count() could be easily wrapped in a function, resulting in :
.candidateKey({}) . Really, the syntax may well end up more like : (count (project Document to {Element})) == (count Document) making the function version : (key {Element} isCandidateKeyOf Document) , seeing as I have a bit of a soft spot for lisp :) -- cwillu ''Can you try again? I'm also unfamiliar with the English you are using. What does "projecting" the table down a keyset mean? What's an Element, what's a Position?'' Element and Position refer to the keys in the table definitions above. Projecting is one of the fundamental operations on a relational table, see RelationalProjection. ''I see that Element and Position are keys in the tables. But what are they? What are they used for? What do they mean?'' Quote: "Normal editing of the text would occur by creating a new element and modifying/adding the Position to reference it." In other words, Element is some block of text, Position is where that element is in the text. But this doesn't really matter anyway, since it's already been stated that the more direct "Index Character" mapping is probably more appropriate. -- cwillu --------------------- '''RPN Calculator Toy Example''' This is from a usenet message on RPN calculator examples. It illustrates how TableOrientedProgramming can be used to simplify a project. Most of the information about the calculator keys is in a table (see bottom of listing) rather than in code. The table-lized version is easier to read than the same info as code in my opinion (especially in a table browser as opposed to ASCII). Here is a quicky FoxPro-based Reverse Polish calculator script that uses a table to define the buttons and their action. Given a choice, I would probably have used parameters to pass around more record references instead of leaving it to global context (one of XBase's S.E. weaknesses) For example, passing around a PHP-style associative array for references to the looked-up Keys (a table) record. It only does integers, and the validation is rather skimpy. Also, I don't really need the "Op" column since the operations happen to fit the display characters. However, I assumed that they could be different, such as displaying "X" for multiplication instead of an asterisk. (Shayne originally requested floating point. I skipped that this time around and just did integers because it would have added more validation and formatting nitty gritty that I thought perhaps distracted from structural issues. I hope this is not a problem. Also, some news-readers may mangle the formatting and indentation. If so, I apologize. Try a Courier font if you have problems. Tabs also somehow got mixed in, and you know what they do to formatting.) Regarding this line here: calc = operand1 &theOp operand2 The single ampersand implies a syntactical substitution. Thus, if TheOp is "+", then this gets executed: calc = operand1 + operand2 Note that I still don't consider this example very representative of applications that I encounter. But, I thought it might be interesting to see what and how people think of it. (begin program code) ***** Procedure calculator set compatible foxplus set readborder on set deleted on set exact on set confirm on set safety off close data select a use keys.dbf alias keys select b use stack.dbf alias stack zap butno = 0 dusplay = "" && number display ("display" is a reserved word) *---define GUI window and event handling IF NOT WEXIST("form1") DEFINE WINDOW form1 ; AT 8, 40 ; SIZE 14,28 ; TITLE "Calc" ; FONT "Courier New", 10 ; FLOAT ; CLOSE ; MINIMIZE ; SYSTEM ; COLOR RGB(,,,192,192,192) ENDIF activate window form1 && displays buttons generated from table select keys scan temp = charcode tempparm = '"' + charcode + '"' @ Yloc, Xloc get butno ; picture "@*HN " + temp valid butpress(&tempparm) endscan activate window form1 read cycle modal return *-------------------- procedure butpress parameter theKey select keys locate for upper(keys->charcode) = upper(thekey) do case case keys->optype = 'K' && digit constants dusplay = dusplay + charcode case keys->optype = 'C' && commands do commands case keys->optype = 'P' && math operation do operations with keys->op endcase &&----display update @ 1,1 say dusplay + space(25 - len(dusplay)) show gets return *-------------------------- procedure commands do case case keys->charcode = 'P' && push do push with dusplay dusplay = "" case keys->charcode = 'C' && clear dusplay = "" case keys->charcode = 'Q' && quit deactivate window form1 close all cancel endcase return *-------------------------- procedure operations parameter theOp raw1 = pop() raw2 = dusplay raw1 = iif(empty(raw1),'0',raw1) && convert blank to zero raw2 = iif(empty(raw2),'0',raw2) operand1 = val(raw1) operand2 = val(raw2) && [insert division by zero check here] calc = operand1 &theOp operand2 dusplay = ltrim(str(int(calc))) return *-------------------------- procedure push(pushme) select stack append blank replace thevalue with pushme return *-------------------------- function pop select stack result = "" goto bottom if .not. eof() result = stack->thevalue delete endif return(result) *-------------------------- (end program code) Table: Keys Charcode Optype Op Descript Xloc Yloc 0 K 5.00 10.00 1 K 5.00 4.00 2 K 10.00 4.00 3 K 15.00 4.00 4 K 5.00 6.00 5 K 10.00 6.00 6 K 15.00 6.00 7 K 5.00 8.00 8 K 10.00 8.00 9 K 15.00 8.00 P C Push 10.00 10.00 + P + Plus 20.00 10.00 - P - Minus 20.00 4.00 * P * Times 20.00 6.00 / P / Divide 20.00 8.00 C C Clear 15.00 10.00 Q C Quit 5.00 12.00 The other table, "stack", has only one column, "theValue". -T- --------------------- See also: OoBusinessExamples