Table Oriented Programming Example

last modified: May 21, 2005

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

<Table>.project({<Key>},).count() == <Table>.count()

could be easily wrapped in a function, resulting in

<Table>.candidateKey({<key>},)

.

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


Loading...