Table Oriented Programming Example
      
      
        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)
      
      
      
        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
      
      
        - 
                  K                         5.00     10.00
        
 
        - 
                  K                         5.00      4.00
        
 
        - 
                  K                        10.00      4.00
        
 
        - 
                  K                        15.00      4.00
        
 
        - 
                  K                         5.00      6.00
        
 
        - 
                  K                        10.00      6.00
        
 
        - 
                  K                        15.00      6.00
        
 
        - 
                  K                         5.00      8.00
        
 
        - 
                  K                        10.00      8.00
        
 
        - 
                  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      /  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