Tuesday 9 June 2015

Arrays

Arrays are great.

In a lot of languages they form the only temporary repository of related information you have access to and so are used and abused regularly.

Perhaps because Progress has such quick and easy access to the database and temp-tables its array handling has been somewhat neglected. Oh and they start at 1, which to many programmers is a unforgivably bad form.

So what can you and cant you do?


You can define fixed length and indeterminate length arrays.

Fixed:

DEF VAR MyArray AS INTEGER EXTENT 10.

Indeterminate:

DEF VAR MyArray AS INTEGER EXTENT.

Slightly weird syntax but there it is, once we have our indeterminate length array we can tell it how long it is.

EXTENT(MyArray) = 4.

But don't be fooled, our array is now permanently stuck at 4, so:

EXTENT(MyArray) = 4.
EXTENT(MyArray) = 5.


Will get you an error, it is in no way a dynamic or variable length array.


Initialising.

Like most languages you can define that values as you start:

DEF VAR MyArray AS INTEGER EXTENT 5 INIT [1,2,3,4,5].

And you can clear out the whole array with a single line of code:

DEF VAR MyArray AS INT EXTENT 5 INIT [1,2,3,4,5].

DISPLAY myArray.

MyArray = 0.

DISPLAY myArray.


Comparisons.

Consider the following code snipit.

DEF VAR MyArray AS INTEGER EXTENT 5 INIT [1,2,3,4,5].
DEF VAR YourArray AS INTEGER EXTENT 5 INIT [1,2,4,4,5].

MESSAGE MyArray = YourArray.

You might hope it would say "No" as the two arrays are different, no such luck...
---------------------------
Error
---------------------------
** Only individual array elements allowed in expressions. (361)
**  Could not understand line 5. (196)
---------------------------
OK  
---------------------------

To be fair Javascript would give a similar if rather less helpful, result.

<script>
var cars = [1,2,3,4,5];
var cars2 = [1,2,3,4,5];

alert (cars == cars2);

</script>

You get a "False" alert box, but its really asking if they are the same object, which of course they are not.

C, now that's were it's at, just two lumps of memory that are either the same or they aren't (ok, the same for the length of MyArray):

int MyArray[] = {1,2,3,4,5};
int YourArray[] = {1,2,4,4,5};

if(memcmp(MyArray,YourArray,sizeof(MyArray)) == 0)

I miss those days. Given how the Javascript result could lead you up the garden path its perhaps best that Progress at least gives a syntax error.

So you're left with the step by step:

DEF VAR MyArray AS INTEGER EXTENT 5 INIT [1,2,3,4,5].
DEF VAR YourArray AS INTEGER EXTENT 5 INIT [1,2,4,4,5].
DEF VAR vi AS INTEGER NO-UNDO.

DO vi = 1 TO EXTENT(MyArray):

    IF MyArray[vi] <> YourArray[vi] THEN DO:
        Message "Different".
        LEAVE.
    END.

END.

Sorting.

So here Progress wins, with most languages you're writing sorts like mama used to make, bubble sorts from high school computer class, with Progress we make use of the simple and close at hand database (or in this case TEMP-TABLE) connection.

Get your whole array, bung it in an indexed temp temp-table and let progress take the strain:

DEF TEMP-TABLE ttMyTable
    FIELD iValue AS INTEGER.
   
DEF VAR MyArray AS INTEGER EXTENT 13 INIT [1,2,3,4,5,2,4,65,654,7,43,3,12].
DEF VAR vi AS INTEGER NO-UNDO.

DO vi = 1 TO EXTENT(MyArray):

    CREATE ttMyTable.
    ASSIGN
        ttMyTable.iValue = MyArray[vi].
    RELEASE ttMyTable.

END.

FOR EACH ttMyTable BY iValue:
    DISPLAY ttMyTable.iValue.
END.

Sorted.

2 and 3 dimensional arrays.

Er... no. You'd have to work around this with a a temp-table, so to express:

/*
1,2,3
4,5,6
7,8,9
*/

/* Definition */

DEFINE VARIABLE viX AS INTEGER     NO-UNDO.
DEFINE VARIABLE viY AS INTEGER     NO-UNDO.

DEF TEMP-TABLE ttMy2dArray
    FIELD ix AS INTEGER
    FIELD iy AS INTEGER
    FIELD ivalue AS INTEGER.

/* Populate */

DO viY = 1 TO 3:
    DO viX = 1 TO 3:

        CREATE ttMy2dArray.

        ASSIGN
            ttMy2dArray.iX = viX
            ttMy2dArray.iY = viY
            ttMy2dArray.iValue = INT(SUBSTRING("123456789",vix + ((viy - 1 )* 3), 1)).

        RELEASE ttMy2dArray.
    END.
END.

/* Whats the center number, 2 dwon 2 accross*/

FIND FIRST ttMy2dArray WHERE ttMy2dArray.iX = 2 
                         AND ttMy2dArray.iY = 2 NO-ERROR.

IF AVAIL ttMy2dArray THEN
    DISPLAY ttMy2dArray.iValue.


Ta, da, note; we'll stick with Progress's idea of starting at array position 1.

Arrays of objects.

That a TEMP-TABLE record, so no need.

Conclusion

So that's the Progress take on arrays, a lack of some of the pre written functions that a PHP programmer would take for granted, but nothing a little lateral thinking a does of TEMP-TABLES cant sort out.

No comments:

Post a Comment