Four Js Development Tools Forum

Discussions by product => Genero BDL => Topic started by: Benjamin G. on August 20, 2024, 12:17:58 pm



Title: Why different initialization logic ?
Post by: Benjamin G. on August 20, 2024, 12:17:58 pm
Hello,

I wonder why an array static and dynamic don't react in the same way?

Sample code :

MAIN
  TYPE tdata RECORD
      i INTEGER
     ,s STRING
     ,f DECIMAL(10,2)
     ,d date
     END RECORD
  DEFINE fixarr array[1] OF tdata
  DEFINE dynarr DYNAMIC array OF tdata

  DISPLAY 'fixed array ....'
    DISPLAY '   fixarr[1].i :',IIF(fixarr[1].i IS NULL,' IS NULL',fixarr[1].i)
    DISPLAY '   fixarr[1].s :',IIF(fixarr[1].s IS NULL,' IS NULL',fixarr[1].s)
    DISPLAY '   fixarr[1].f :',IIF(fixarr[1].f IS NULL,' IS NULL',fixarr[1].f)
    DISPLAY '   fixarr[1].d :',IIF(fixarr[1].d IS NULL,' IS NULL',fixarr[1].d)
  DISPLAY 'dynamic array ....'
    DISPLAY '   dynarr[1].i :',IIF(dynarr[1].i IS NULL,' IS NULL',dynarr[1].i)
    DISPLAY '   dynarr[1].s :',IIF(dynarr[1].s IS NULL,' IS NULL',dynarr[1].s)
    DISPLAY '   dynarr[1].f :',IIF(dynarr[1].f IS NULL,' IS NULL',dynarr[1].f)
    DISPLAY '   dynarr[1].d :',IIF(dynarr[1].d IS NULL,' IS NULL',dynarr[1].d)
END MAIN
   
Results :
   
fixed array ....
   fixarr[1].i :          0
   fixarr[1].s : IS NULL
   fixarr[1].f : IS NULL
   fixarr[1].d :31.12.1899
dynamic array ....
   dynarr[1].i : IS NULL
   dynarr[1].s : IS NULL
   dynarr[1].f : IS NULL
   dynarr[1].d : IS NULL

Regards


Title: Re: Why different initialization logic ?
Post by: Rene S. on August 20, 2024, 01:07:04 pm
* dynamic arrays are initially empty. New elements will be initialized to NULL
* static arrays are initialized to zero (Genero has inherited this from Informix). Initialized "to zero" means: the underlying memory is initialized with zeros.
* for some types (char, varchar, dec, money, text, datetime,  interval)  initializing "to zero" produces NULL values.
* some other (the numeric types: smallint, int, smallfloat, float) behave like their C counterparts: the variables have the value 0.
* DATE variables count days since 31.12.1899 - this implies initialize "to zero" produces 31.12.1899

BTW: Informix 4gl is not initializing local variables.


Title: Re: Why different initialization logic ?
Post by: Benjamin G. on August 20, 2024, 01:58:17 pm
Hello,

documentation is very clear about that (https://4js.com/online_documentation/fjs-fgl-manual-html/#fgl-topics/c_fgl_variables_008.html)
the question was one of principle, should the programmer always assume that a variable is always initialized to NULL and is responsible for setting it to the correct value before using either with the “define initializer” or with a LET ...

regards


Title: Re: Why different initialization logic ?
Post by: Sebastien F. on August 20, 2024, 02:48:28 pm
Benjamin,

You can rely on the fact that variables are initialized by default as described in the doc (=> depending on the data type, NULL or zero)

If the default value matches what you need, you don't have to initialize the variables with custom code.

Seb


Title: Re: Why different initialization logic ?
Post by: Benjamin G. on August 20, 2024, 03:21:44 pm
that was our problem. Migrating an I4gl code to bdl

the initial I4gl code was :
  define i smallint
  define mytotals[100] of integer

 let i = 0
 foreach ...
    let i  i= i+1
    if i > 100 then
      message "ARRAY TO SMALL ..."
      exit foreach
    end if
    let mytotals=mytotals + someNotNullValueFromDb ...
  end foreach
 
  ---> code was ok

the new bdl code :
  define i smallint
  define mytotals dynamic array of integer

 foreach ...
    let mytotals[i:=i+1]=mytotals + someNotNullValueFromDb ...
  end foreach

  code was ko : all mytotals  NULL ...

That was our initial problem ...


Title: Re: Why different initialization logic ?
Post by: Sebastien F. on August 20, 2024, 03:44:40 pm
Your last code example does not seem to be the real one because mytotals is an array and it is used without an index.

Code
  1.    let mytotals[i:=i+1]=mytotals + someNotNullValueFromDb ...

I am not sure to get the purpose of this code (do you sum sub-totals sequentially?)

Anyway, yes, when using a DYNAMIC ARRAY you need to initialize an INTEGER element to zero.

You may also take care of the value you add, if it's NULL it gives a NULL result.

Code
  1. FOREACH ... INTO curr_value
  2.    LET mytotals[i:=i+1] = 0
  3.    LET mytotals[i] = <whatever> + NVL(curr_value,0)
  4. END FOREACH


Seb


Title: Re: Why different initialization logic ?
Post by: Reuben B. on August 21, 2024, 02:44:20 am
Ben,

I think it is an interesting question you ask.  However remember that DYNAMIC ARRAY were added to the Genero language in the late 1990's / early 2000's so answer maybe lost in time.  We obviously have to respect Informix-4gl behaviour.

Also back in the day Informix-4gl could be compiled to p-code (.4go) and c-code (.4gi) and with c-code you had to explicitly initialise variables (or else you got the garbage that was in memory where your variable was allocated). So I think we sensibly followed the .4go behaviour.

I bump into this initialisation difference with simple examples ...

Code
  1. MAIN
  2.    DEFINE rec RECORD
  3.        field1 INTEGER,
  4.        field2 STRING,
  5.        field3 DATE
  6. END RECORD
  7.  
  8.    OPEN WINDOW w WITH FORM base.Application.getProgramName()
  9.    INPUT BY NAME rec.* ATTRIBUTES(WITHOUT DEFAULTS=TRUE, UNBUFFERED)
  10. END MAIN

will render with 0  in the INTEGER field and 31/12/1899 in the DATE field

Whilst with arrays

Code
  1. MAIN
  2.    DEFINE arr DYNAMIC ARRAY OF RECORD
  3.        field1 INTEGER,
  4.        field2 STRING,
  5.        field3 DATE
  6. END RECORD
  7.  
  8.    OPEN WINDOW w WITH FORM  base.Application.getProgramName()
  9.    INPUT ARRAY arr FROM scr.* ATTRIBUTES(WITHOUT DEFAULTS=TRUE, UNBUFFERED)
  10. END MAIN

 the INTEGER and DATE field are blank

I have to remember to add INITIALIZE rec.* TO NULL in my simple INPUT examples so that I don't see the 0 and 31/12/1899.  The 0 and 31/12/1899 are annoying as a) they mean placeholder does not appear, and b) in the case of the dateedit, the calendar opens upto 31/12/1899 as opposed to TODAY if it is null.


I always thought the DYNAMIC ARRAY design decision and not initialising to 0's was something to do with runtime speed / memory consumption.  Run the following ...

Code
  1. MAIN
  2. DEFINE arr DYNAMIC ARRAY OF INTEGER
  3. DEFINE i INTEGER
  4. CONSTANT MAX_SIZE = 100000000
  5.  
  6.  
  7.    LET arr[MAX_SIZE] = 0
  8.    --FOR i = 1 TO MAX_SIZE
  9.    --    LET arr[i] = 0
  10.    --END FOR
  11.    MENU ""
  12.        ON ACTION ACCEPT
  13.            EXIT MENU
  14.    END MENU
  15. END MAIN

... and note the memory consumption.

Now repeat with the comments removed which mimics what would happen if the dynamic array rows were populated with 0's.  Do you see higher numbers?


Reuben


 



Title: Re: Why different initialization logic ?
Post by: Benjamin G. on August 21, 2024, 08:47:02 am
Hi,

I've made a test with Informix dynamic arrays (version 7.50FC4 compiled mode c4gl) and results are :

fixed array ....
   fixarr[1].i : -1
   fixarr[1].s : ˙čř
   fixarr[1].f : NULL
   fixarr[1].d : 31.12.1899
dynamic array ....
   dynarr[1].i : NULL
   dynarr[1].s : NULL
   dynarr[1].f : NULL
   dynarr[1].d : NULL

and with I4gl

fixed array ....
   fixarr[1].i : 0
   fixarr[1].s : NULL
   fixarr[1].f : NULL
   fixarr[1].d : NULL
dynamic array ....
   dynarr[1].i : NULL
   dynarr[1].s : NULL
   dynarr[1].f : NULL
   dynarr[1].d : NULL


As you can see, in C mode a static array contains garbage and the dynamic array is initialized to NULL
and in P-code (i4gl) a static array is initialized NULL and integer 0 and the dynamic array is initialized to NULL (seems like BDL ...)
The initial question was simply whether it wouldn't be more logical to always initialize an ARRAY to null in order to avoid confusion. I haven't found in the documentation any explanation of how an array is initialized by default.
For Seb, the example I've given is obviously not the production code, I just wanted to give the general idea of the situation.

Regards


Title: Re: Why different initialization logic ?
Post by: Sebastien F. on August 21, 2024, 09:21:04 am
Please provide the source code when you show such test output.

We will review the BDL doc and add notes about array element initializations.

Seb


Title: Re: Why different initialization logic ?
Post by: Benjamin G. on August 21, 2024, 09:46:21 am
Hi,

the BDL source code was in my first post
my last post source code was made for Informix 4gl  not BDL ...
Code
  1. MAIN
  2.  DEFINE s CHAR(40)
  3.  DEFINE fixarr array[1] OF RECORD
  4.      i INTEGER
  5.     ,s CHAR(20)
  6.     ,f DECIMAL(10,2)
  7.     ,d date
  8.        END RECORD
  9.  DEFINE dynarr DYNAMIC array OF RECORD
  10.      i INTEGER
  11.     ,s CHAR(20)
  12.     ,f DECIMAL(10,2)
  13.     ,d date
  14.        END RECORD
  15.  
  16.  DISPLAY 'fixed array ....'
  17.    LET s =MYisNull(fixarr[1].i)
  18.    DISPLAY '   fixarr[1].i : ',s CLIPPED
  19.    LET s =MYisNull(fixarr[1].s)
  20.    DISPLAY '   fixarr[1].s : ',s CLIPPED
  21.    LET s =MYisNull(fixarr[1].f)
  22.    DISPLAY '   fixarr[1].f : ',s CLIPPED
  23.    LET s =MYisNull(fixarr[1].d)
  24.    DISPLAY '   fixarr[1].d : ',s CLIPPED
  25.  
  26.  ALLOCATE ARRAY dynarr[1]
  27.  DISPLAY 'dynamic array ....'
  28.    LET s =MYisNull(dynarr[1].i)
  29.    DISPLAY '   dynarr[1].i : ',s CLIPPED
  30.    LET s =MYisNull(dynarr[1].s)
  31.    DISPLAY '   dynarr[1].s : ',s CLIPPED
  32.    LET s =MYisNull(dynarr[1].f)
  33.    DISPLAY '   dynarr[1].f : ',s CLIPPED
  34.    LET s =MYisNull(dynarr[1].d)
  35.    DISPLAY '   dynarr[1].d : ',s CLIPPED
  36. END MAIN
  37.  
  38. FUNCTION MYisNull(f)
  39.  DEFINE f char(40)
  40.  IF f IS NULL THEN
  41.    RETURN "NULL"
  42.  END IF
  43.  RETURN f
  44. END FUNCTION
  45.  
[/color]


Regards