Page 1 of 2

FWH 18.08: Gets with loop variable as array subscript

Posted: Thu Sep 27, 2018 6:26 am
by nageswaragunupudi
There are occassions when we need to Get values of array elements like, aValue[ 1 ], aValue[ 2 ], ... , aValue[ n ]. If they are not many we can write code something like this:

Code-1: (Correct)

Code: Select all

@  40, 20 SAY aPrompts[ 1 ] SIZE 80,24 PIXEL OF oDlg
@  40,110 GET aGets   [ 1 ] VAR aValues[ 1 ] SIZE 120,28 PIXEL OF oDlg
@  70, 20 SAY aPrompts[ 2 ] SIZE 80,24 PIXEL OF oDlg
@  70,110 GET aGets   [ 2 ] VAR aValues[ 2 ] SIZE 120,28 PIXEL OF oDlg
@ 100, 20 SAY aPrompts[ 3 ] SIZE 80,24 PIXEL OF oDlg
@ 100,110 GET aGets   [ 3 ] VAR aValues[ 3 ] SIZE 120,28 PIXEL OF oDlg
@ 130, 20 SAY aPrompts[ 4 ] SIZE 80,24 PIXEL OF oDlg
@ 130,110 GET aGets   [ 4 ] VAR aValues[ 4 ] SIZE 120,28 PIXEL OF oDlg
 
This works well.
But where there are many values, we would like to create the Says and Gets in a loop we may write code something like this:

Code-2: (Wrong)

Code: Select all

   nRow     := 40
   for n := 1 to nLen
      @ nRow, 20 SAY aPrompts[ n ] SIZE 80,24 PIXEL OF oDlg
      @ nRow,110 GET aGets[ n ] VAR aValues[ n ] ;
         SIZE 120,28 PIXEL OF oDlg
      nRow  += 30
   next
 
But this does not work. We get a runtime error.

Reason: For every Get, its bSetGet codeblock is assigned with
{ |u| If( PCount() == 0, aValues[ n ], aValues[ n ] := u ) }.
During runtime this codeblock is evaluated with the value of 'n', which is always nLen+1 and array bound error occurs.

To overcome this problem, we need to create the Gets in a separate function using the concept of detatched locals. Here is a working sample using this principle.

Code-3: (Correct working sample)

Code: Select all

#include "fivewin.ch"

function Main()

   local oDlg
   local aPrompts := { "First", "Second", "Third", "Fourth" }
   local aValues  := { Space( 10 ), Space( 10 ), Space( 10 ), Space( 10 ) }
   local aGets[ 4 ], n, nRow

   DEFINE DIALOG oDlg SIZE 400,250 PIXEL TRUEPIXEL

   nRow     := 40

   for n := 1 to 4
      @ nRow, 20 SAY aPrompts[ n ] SIZE 80,24 PIXEL OF oDlg
      aGets[ n ] := CreateGet( nRow, 110, aValues, n, oDlg )
      nRow  += 30
   next

   @ nRow, 20 BUTTON "Close" SIZE 100,30 PIXEL OF oDlg ACTION oDlg:End()

   ACTIVATE DIALOG oDlg CENTERED

   XBROWSER aValues // Ceck the values

return nil

function CreateGet( nRow, nCol, aArray, nEle, oDlg )

   local oGet

   @ nRow, nCol GET oGet VAR aArray[ nEle ] SIZE 120,24 PIXEL OF oDlg

return oGet
 
Enhacement in FWH 18.08:

It is no more necessary to create the Gets in a separate function. We can create the gets straight away in the loop iteslef in a single command. This is a working sample, using the new clause SUBSCTIPT:

Syntax:
@ r, c GET aArray SUBSCRIPT n // where n is the loop variable

Code-4: ( Correct FWH 18.08 )

Code: Select all

#include "fivewin.ch"

function Main()

   local oDlg
   local aPrompts := { "First", "Second", "Third", "Fourth" }
   local aValues  := { Space( 10 ), Space( 10 ), Space( 10 ), Space( 10 ) }
   local aGets[ 4 ], n, nRow := 40

   DEFINE DIALOG oDlg SIZE 400,250 PIXEL TRUEPIXEL

   nRow     := 40
   for n := 1 to 4
      @ nRow, 20 SAY aPrompts[ n ] SIZE 80,24 PIXEL OF oDlg
      @ nRow,110 GET aGets[ n ] VAR aValues SUBSCRIPT n ;
         SIZE 120,28 PIXEL OF oDlg
      nRow  += 30
   next

   @ nRow, 20 BUTTON "Close" SIZE 100,30 PIXEL OF oDlg ACTION oDlg:End()

   ACTIVATE DIALOG oDlg CENTERED

   XBROWSER aValues

return nil
 
Let us now consider a bit more complex case of a multi dimentional array consisting of Prompts in the first column, variables in the second column and pictures in the third column. Here the get variable is aData[ n, 2 ] where n is the loop variable.

In this sample, let us also try using the recently introduced syntax:
@ r, c SAY ...GET ...

Code-5 (Working sample FWH 1808)

Code: Select all

function ArrayGets

   local oDlg
   local aData    := { { "First  ",  Space( 10 ), nil         }, ;
                       { "Second ",  Space( 10 ), "@!"        }, ;
                       { "Third  ",  DATE(),      "@D"        }, ;
                       { "Fourth ",  0,           "99,999.99" }  }

   local aGets[ 4 ], n, nRow

   DEFINE DIALOG oDlg SIZE 400,250 PIXEL TRUEPIXEL

   nRow     := 40
   for n := 1 to 4

      @ nRow, 20 SAY aData[ n, 1 ] GET aGets[ n ] VAR aData SUBSCRIPT n, 2 ;
         PICTURE aData[ n, 3 ] SIZE 240,28 PIXEL OF oDlg

      nRow  += 30
   next

   @ nRow, 20 BUTTON "Close" SIZE 100,30 PIXEL OF oDlg ACTION oDlg:End()

   ACTIVATE DIALOG oDlg CENTERED

   XBROWSER aData // Check

return nil
 
This enhancement in FWH 1808 makes programming Gets of arrays using loop variables.

This new syntax is not applicable to gets from resources as such gets are not generally redefined in a loop.

Re: FWH 18.08: Gets with loop variable as array subscript

Posted: Thu Sep 27, 2018 9:09 am
by ellano
Thanks for this improvement!

It will be marvelous if we can use it like this:

Code: Select all

LOCAL n, nIDSay:=900, nIDGet:=600, nLen:=20

for n := 1 to nLen
    REDEFINE SAY oSay[n]              SUBSCRIPT n ID nIDSay IDSUBSCRIPT nIDSay OF oFld:aDialogs[1]   //Say, Get pair
    REDEFINE GET oGet[n] VAR aData[n] SUBSCRIPT n ID nIDGet IDSUBSCRIPT nIDGET OF oFld:aDialogs[1] 
    nIDGet++
    nIDSay++
 next
May I suggest it as an enhancement on a future version?

Emiliano Llano Díaz

Re: FWH 18.08: Gets with loop variable as array subscript

Posted: Thu Sep 27, 2018 10:05 am
by nageswaragunupudi
We can consider extending this feature to resource also, if you think it will be useful.

Note: It is not "VAR aData[ n ] SUBSCRIPT n"
It should be "VAR aData SUBSCRIPT n"

There is no need for a subscript clause for SAYs

Re: FWH 18.08: Gets with loop variable as array subscript

Posted: Thu Sep 27, 2018 10:29 am
by ellano
At least for me it will reduce my code from several dozen lines to a handful. :D

Re: FWH 18.08: Gets with loop variable as array subscript

Posted: Thu Sep 27, 2018 10:46 am
by nageswaragunupudi
Ok.
We will provide this in 18.08

Re: FWH 18.08: Gets with loop variable as array subscript

Posted: Sun Jan 27, 2019 6:34 pm
by ellano
Could you please indicate me what I am doing wrong here?

Code: Select all

nIDGet:=116
nLen:=62
FOR n := 47 TO nLen
    REDEFINE GET aPedg[n,2] SUBSCRIPT n ID nIDGet IDSUBSCRIPT nIDGET OF oFld:aDialogs[4] UPDATE READONLY FONT oFuente[2]
    nIDGet++
NEXT
I am trying to convert this to the new syntax:

Code: Select all

REDEFINE GET aPedg[47,2] ID 116 OF oFld:aDialogs[4] UPDATE READONLY FONT oFuente[2]
REDEFINE GET aPedg[48,2] ID 117 OF oFld:aDialogs[4] UPDATE READONLY FONT oFuente[2]
REDEFINE GET aPedg[49,2] ID 118 OF oFld:aDialogs[4] UPDATE READONLY FONT oFuente[2]
REDEFINE GET aPedg[50,2] ID 119 OF oFld:aDialogs[4] UPDATE READONLY FONT oFuente[2]
REDEFINE GET aPedg[51,2] ID 120 OF oFld:aDialogs[4] UPDATE READONLY FONT oFuente[2]
...
Thanks
Emiliano Llano Díaz

Re: FWH 18.08: Gets with loop variable as array subscript

Posted: Mon Jan 28, 2019 2:59 pm
by nageswaragunupudi
Please try

Code: Select all

nIDGet:=116
nLen:=62
FOR n := 47 TO nLen
    REDEFINE GET aPedg SUBSCRIPT n,2 ID nIDGet IDSUBSCRIPT nIDGET OF oFld:aDialogs[4] UPDATE READONLY FONT oFuente[2]
    nIDGet++
NEXT

Re: FWH 18.08: Gets with loop variable as array subscript

Posted: Mon Jan 28, 2019 3:29 pm
by ellano
Mr. Rao:

Thanks for your answer.

I did try that combination (among another dozen ones that, of course, I do not remember) in despair but I got this enigmatic error:

.\prg\register.PRG(777) Error E0030 Syntax error "syntax error at 'GET'"

Same for this code:

Code: Select all

* original:
*REDEFINE GET oGet[64] VAR aPedg[23,2] MEMO ID 108 OF oFld:aDialogs[4] UPDATE READONLY FONT oFuente[2]

nIDGet:=108
nLen  :=30
n     :=64

FOR nIDVar := 23 TO nLen
    REDEFINE GET oGet SUBSCRIPT n VAR aPedg SUBSCRIPT nIDVar,2 MEMO ID nIDGet IDSUBSCRIPT nIDGET OF oFld:aDialogs[4] UPDATE READONLY FONT oFuente[2]
    nIDGet++
    n++
NEXT 
...

*Original
*REDEFINE GET aPedg[47,2] ID 116 OF oFld:aDialogs[4] UPDATE READONLY FONT oFuente[2]

nIDGet:=116
nLen:=62
FOR n := 47 TO nLen
    REDEFINE GET aPedg SUBSCRIPT n,2 ID nIDGet IDSUBSCRIPT nIDGET OF oFld:aDialogs[4] UPDATE READONLY FONT oFuente[2]
    nIDGet++
NEXT
 
FWH 18.10

Emiliano Llano Díaz

Re: FWH 18.08: Gets with loop variable as array subscript

Posted: Mon Jan 28, 2019 5:04 pm
by cnavarro
Emiliano, clause duplicate?

REDEFINE GET oGet SUBSCRIPT n VAR aPedg SUBSCRIPT nIDVar,2 MEMO ID nIDGet IDSUBSCRIPT nIDGET OF oFld:aDialogs[4] UPDATE READONLY FONT oFuente[2]

Re: FWH 18.08: Gets with loop variable as array subscript

Posted: Mon Jan 28, 2019 5:20 pm
by ellano
Mr. Navarro:

Thanks for your concern.
Maybe in that one, but in the other one? (gives same cryptic error):

.\prg\register.PRG(783) Error E0030 Syntax error "syntax error at 'GET'"

Code: Select all

* Original code
* REDEFINE GET aPedg[47,2] ID 116 OF oFld:aDialogs[4] UPDATE READONLY FONT oFuente[2]
nIDGet:=116
nLen:=62
FOR n := 47 TO nLen
    REDEFINE GET aPedg SUBSCRIPT n,2 ID nIDGet IDSUBSCRIPT nIDGET OF oFld:aDialogs[4] UPDATE READONLY FONT oFuente[2]
    nIDGet++
NEXT

Re: FWH 18.08: Gets with loop variable as array subscript

Posted: Mon Jan 28, 2019 5:33 pm
by cnavarro
Emiliano, try
REDEFINE GET aPedg SUBSCRIPT n,2 ID nIDGet OF oFld:aDialogs[4] UPDATE READONLY FONT oFuente[2]

Re: FWH 18.08: Gets with loop variable as array subscript

Posted: Tue Jan 29, 2019 11:10 am
by ellano
Thanks. That make it work, but then the whole structure is useless since it attach all the GET array to one ID.

At least it narrows the error down to the IDSUBSCRIPT part that seems to be giving the problem (and error)

Emiliano Llano Díaz

Re: FWH 18.08: Gets with loop variable as array subscript

Posted: Tue Jan 29, 2019 11:41 am
by cnavarro
ellano wrote:Thanks. That make it work, but then the whole structure is useless since it attach all the GET array to one ID.

At least it narrows the error down to the IDSUBSCRIPT part that seems to be giving the problem (and error)

Emiliano Llano Díaz
Emiliano

Code: Select all


FOR n := 47 TO nLen
    REDEFINE GET aPedg SUBSCRIPT n,2 ID nIDGet OF oFld:aDialogs[4] UPDATE READONLY FONT oFuente[2]
    nIDGet++
NEXT

 

Re: FWH 18.08: Gets with loop variable as array subscript

Posted: Tue Jan 29, 2019 2:46 pm
by ellano
Thank you for your advice. We have now two cases:

Code: Select all

* This one works:
nID:=116
FOR nIDGet := 47 TO 62
    REDEFINE GET aPedg SUBSCRIPT nIDGet,2 ID nID OF oFld:aDialogs[4] UPDATE READONLY FONT oFuente[2]
    nID++
NEXT

* This one, a little more complex, has an error E0030 on GET
nIDGet:=  64
nID   := 108
FOR nIDVar := 23 TO 30
    REDEFINE GET oGet[nIDGet] VAR aPedg SUBSCRIPT nIDVar,2 MEMO ID nID OF oFld:aDialogs[4] UPDATE READONLY FONT oFuente[2]
    nID++
    nIDGet++
NEXT

Re: FWH 18.08: Gets with loop variable as array subscript

Posted: Tue Jan 29, 2019 3:34 pm
by nageswaragunupudi
This is correct

Code: Select all

nID:=116
FOR nIDGet := 47 TO 62
    REDEFINE GET aPedg SUBSCRIPT nIDGet,2 ID nID OF oFld:aDialogs[4] UPDATE READONLY FONT oFuente[2]
    nID++
NEXT