FWH 18.08: Gets with loop variable as array subscript

User avatar
nageswaragunupudi
Posts: 8017
Joined: Sun Nov 19, 2006 5:22 am
Location: India
Contact:

FWH 18.08: Gets with loop variable as array subscript

Post 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.
Regards

G. N. Rao.
Hyderabad, India
ellano
Posts: 107
Joined: Tue Sep 15, 2009 7:52 am

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

Post 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
User avatar
nageswaragunupudi
Posts: 8017
Joined: Sun Nov 19, 2006 5:22 am
Location: India
Contact:

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

Post 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
Regards

G. N. Rao.
Hyderabad, India
ellano
Posts: 107
Joined: Tue Sep 15, 2009 7:52 am

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

Post by ellano »

At least for me it will reduce my code from several dozen lines to a handful. :D
User avatar
nageswaragunupudi
Posts: 8017
Joined: Sun Nov 19, 2006 5:22 am
Location: India
Contact:

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

Post by nageswaragunupudi »

Ok.
We will provide this in 18.08
Regards

G. N. Rao.
Hyderabad, India
ellano
Posts: 107
Joined: Tue Sep 15, 2009 7:52 am

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

Post 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
User avatar
nageswaragunupudi
Posts: 8017
Joined: Sun Nov 19, 2006 5:22 am
Location: India
Contact:

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

Post 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
Regards

G. N. Rao.
Hyderabad, India
ellano
Posts: 107
Joined: Tue Sep 15, 2009 7:52 am

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

Post 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
User avatar
cnavarro
Posts: 5792
Joined: Wed Feb 15, 2012 8:25 pm
Location: España

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

Post 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]
C. Navarro
Hay dos tipos de personas: las que te hacen perder el tiempo y las que te hacen perder la noción del tiempo
Si alguien te dice que algo no se puede hacer, recuerda que esta hablando de sus limitaciones, no de las tuyas.
ellano
Posts: 107
Joined: Tue Sep 15, 2009 7:52 am

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

Post 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
User avatar
cnavarro
Posts: 5792
Joined: Wed Feb 15, 2012 8:25 pm
Location: España

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

Post by cnavarro »

Emiliano, try
REDEFINE GET aPedg SUBSCRIPT n,2 ID nIDGet OF oFld:aDialogs[4] UPDATE READONLY FONT oFuente[2]
C. Navarro
Hay dos tipos de personas: las que te hacen perder el tiempo y las que te hacen perder la noción del tiempo
Si alguien te dice que algo no se puede hacer, recuerda que esta hablando de sus limitaciones, no de las tuyas.
ellano
Posts: 107
Joined: Tue Sep 15, 2009 7:52 am

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

Post 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
User avatar
cnavarro
Posts: 5792
Joined: Wed Feb 15, 2012 8:25 pm
Location: España

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

Post 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

 
C. Navarro
Hay dos tipos de personas: las que te hacen perder el tiempo y las que te hacen perder la noción del tiempo
Si alguien te dice que algo no se puede hacer, recuerda que esta hablando de sus limitaciones, no de las tuyas.
ellano
Posts: 107
Joined: Tue Sep 15, 2009 7:52 am

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

Post 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
User avatar
nageswaragunupudi
Posts: 8017
Joined: Sun Nov 19, 2006 5:22 am
Location: India
Contact:

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

Post 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
 
Regards

G. N. Rao.
Hyderabad, India
Post Reply