Published on System iNetwork (http://systeminetwork.com)
Special Initial Values
By linda.harty@penton.com
Created Jun 25 2008 - 17:12

By:
Scott Klement [1]

Most RPG programmers today are familiar with specifying the initialize (INZ) keyword on a D-spec to provide an initial value for a variable. Did you realize, though, that there are special values that you can specify inside the INZ keyword? In this article, I explain these special values and demonstrate how to use them.

Here's a list of the special values that you can use in the INZ keyword:

Keyword Applies to Release Description
*SYS Date fields V3R7 Initialize with the current date from the system clock
*JOB Date fields V3R7 Initialize with the job date
*USER Alphanumeric V4R4 Initialize with the current user profile name
*EXTDFT External DS V4R4 Initialize with the default values from the DDS/DDL
*LIKEDS Derived DS V5R1 Copy initial values of the original data structure
*NULL Java Object V5R1 Set object reference to point to nothing

Using *SYS and *JOB to Initialize Dates

Historically, to set the value of a date, we moved the UDATE or *DATE field into another variable. This action would set the variable to the job date. Or, if we needed the system date, we used the TIME opcode to get the date and time, which was a little more work.

One thing that I dislike about those "good ol' days" is that far too many folks inappropriately used the job date (either *DATE or UDATE). Why? Because moving *DATE was a lot easier than invoking the TIME opcode.

Fortunately, today, getting the current time from the system clock is easy. Simply define a date field and initialize it to *SYS:

     D MyDate          s               D   inz(*sys)
      /free
          dsply ('Current date is ' + %char(MyDate));
          return;
      /end-free

Of course, you do have to remember that the date is set to the system date only when the variable is initialized. For global variables, that means the first time the module is invoked. For variables local to a subprocedure, the date is reinitialized each time the procedure is run, unless the variables are declared as static.

If your program runs in a loop that might need to cross over into the next day, then you might want to update the date from the system clock in the middle of your loop. When you call the %date() BIF with no parameters, the current system date is retrieved.

For example, the following never-ending loop displays the current date from the system clock. Because it calls %date() in the loop, the system date is re-retrieved each time through, so if the program is left running past midnight, the date changes.

     D MyDate          s               D
      /free
          dow 1 = 1;
              MyDate = %date();
              dsply ('Current date is ' + %char(MyDate));
          enddo;

          return;
      /end-free

Most of the time, I think the system date is the right choice when you want to use the current date in an RPG program. Unless someone has changed it with the CHGJOB command (or a similar tool) the job date is the date that your job started. If the job stays active past midnight, the job date will be wrong. Unfortunately, far too many programs contain this mistake!

However, if you do prefer to use the job date, it's not any harder to use than the system date. Just specify *JOB instead of *SYS:

     D MyDate          s               D   inz(*JOB)

Getting the UserID with *USER

The *USER keyword retrieves the current user profile name and stores it in the variable. For example:

     D MyUserId        s             10a   inz(*USER)

Check the value of MyUserId, and you see that it's set to the user profile running your job. Using this feature is much easier than coding a program status data structure (PSDS) or, even worse, calling a CL program just to retrieve the current user profile name.

If you're running a job in which the user profile changes, such as when you do profile swapping or run your program from a network server, *USER is initialized with whomever the current user is at the time that the INZ keyword is executed.

External Data Structures and *EXTDFT

RPG has always been able to declare a data structure as being "like" a record from a file. Did you know that you can also use this feature to set the default values of the fields in the data structure? For example, considering the following physical file:

     A          R EXTDFTF
     A            FIELD1        10A         DFT('SCOTT')
     A            FIELD2        10A         DFT('KLEMENT')
     A            FIELD3         5P 0       DFT(1)

If you want to create a data structure that has the same field names (as above) and starts with whatever values you specify for DFT, you could use code like this:

     D MyDs          e ds                  extname(EXTDFT)
     D                                     inz(*extdft)

Because of the way I've coded that, the MyDS field automatically includes the FIELD1, FIELD2, and FIELD3 values from the DDS. Because I specified the INZ keyword with *EXTDFT, the fields start with "Scott", "Klement", and 1, respectively.

See how easy that was?

Cloning Data Structures with *LIKEDS

The *LIKEDS keyword is very similar to the *EXTDFT one that I just demonstrated, except that it operates on another data structure in the same program instead of operating on an externally defined data structure. For example:

     D DsOne           ds                  qualified
     D   First                       10a   inz('Scott')
     D   Last                        10a   inz('Klement')
     D   Age                          3p 0 inz(102)

     D DsTwo           ds                  likeds(DsOne)
     D                                     inz(*likeds)
      /free
           dsply DsTwo.First;
           dsply DsTwo.Last;
           dsply DsTwo.Age;
           *inlr = *on;
      /end-free

DsOne has subfields that were initialized when the program started up. DsTwo is defined with LIKEDS, and that means that DsTwo has the same subfields as DsOne had. The INZ(*LIKEDS) tells the system to initialize DsTwo to the same initial values that DsOne had.

Initializing Java Objects with *NULL

In V5R1, RPG gained the ability to call methods in Java objects. As part of that support, IBM added an O data type that refers to a Java object. You can use the *NULL special value to initialize the O data type as follows:

     D MyObject        s               O   Class(*java:'java.lang.String')
     D                                     inz(*null)

The inz(*null) means that this object reference field has not yet been associated with an actual Java object in the Java Virtual Machine (JVM).

However, I find INZ(*NULL) useless for the following reasons:

  1. All Java object references are always initialized to *NULL, even if you don't code the INZ keyword.
  2. *NULL is the only possible value for the INZ keyword on a Java object reference field.

Given those points, there's little reason to explicitly code INZ(*NULL). Just code the object reference without the INZ keyword, and you'll be all set.

Good luck, and happy initializing!

Copyright © Penton Media

Source URL: http://systeminetwork.com/article/special-initial-values

Links:
[1] http://systeminetwork.com/author/scott-klement