As part of the latest Technology Refreshes, IBM i 7.5 TR4 and 7.4 TR10, comes an addition to the variable and data structure definitions. It is now possible to use the constant keyword as part of those definitions to protect them from being changed.
Why would I want to do that?
There are times I want to use a variable, rather than a constant. It might be to contain a date. I would not want this to be changed, either on purpose or by accident.
Below is an example:
01 **free 02 dcl-s StartDate date inz(*sys) const ; 03 dsply StartDate ; 04 StartDate = d'2024-07-04' ; |
Line 1: I always program in modern, totally free format, RPG.
Line 2: Definition of a date variable, I have called StartDate. I initialized it with the current time at program initialization. The constant keyword, CONST, follows to define it as an unchangeable constant variable.
Line 3: Display the contents of StartDate.
Line 4: Here I (try to) change the value in StartDate.
As the variable is defined as constant and I am trying to change it, the program will not compile. I see the following in my compile listing:
1 **free 2 dcl-s StartDate date inz(*sys) const ; 3 dsply StartDate ; 4 StartDate = d'2024-07-04' ; ======>aaaaaaaaa *RNF5346 30 a 000400 The operation modifies the field, but the field cannot be modified. |
I can make a data structure a constant too:
01 **free 02 dcl-ds DefaultSettings qualified const ; 03 Currency char(3) inz('USD') ; 04 DateFormat char(4) inz('*USA') ; 05 TimeFormat char(4) inz('*HMS') ; 06 end-ds ; 07 dcl-ds Settings likeds(DefaultSettings) ; 08 eval-corr Settings = DefaultSettings ; 09 Settings.DateFormat = '*MDY' ; |
Lines 2 – 6: This is the definition of a data structure, DafaultSettings, that is a constant. Notice the CONST keyword on line 2.
Lines 3 – 5: I can define subfields and initialize them with various values.
Line 7: I am defining another data structure, Settings, with the LIKEDS keyword to be a copy of DefaultSettings. This means that the two have the same layout, but Settings does not contain the values in DefaultSettings.
Line 8: I use the Eval Corresponding operation code, EVAL-CORR, to copy the values in DefaultSettings to Settings.
Line 9: As Settings was not defined with the constant keyword I can change one of its subfields.
If I place a debug breakpoint after line 9 I can check the values in both data structures.
EVAL DefaultSettings DEFAULTSETTINGS.CURRENCY = 'USD' DEFAULTSETTINGS.DATEFORMAT = '*USA' DEFAULTSETTINGS.TIMEFORMAT = '*HMS' EVAL Settings SETTINGS.CURRENCY = 'USD' SETTINGS.DATEFORMAT = '*MDY' SETTINGS.TIMEFORMAT = '*HMS' |
It is not possible to use the constant on data structure subfields. I tried and received a compile error when I did.
1 **free 2 dcl-ds DefaultSettings qualified ; 3 Currency char(3) inz('USD') const ; ======> aaaaa *RNF3701 20 a 000300 Keyword is not allowed for a subfield definition; keyword is ignored. 4 DateFormat char(4) inz('*USA') ; 5 TimeFormat char(4) inz('*HMS') ; 6 end-ds ; |
The next thing I thought to try was could I change the value in a constant variable in debug?
This is the program I created to test if I could.
01 **free 02 dcl-s StartDate date inz(*sys) const ; 03 dsply StartDate ; |
Line 2: StartDate is defined the same way as it was in the first program.
I placed a debug breakpoint at line 3. And when debug "broke" I tried to change the value in StartDate.
EVAL StartDate = '2023-12-31' |
Line 3: When the value of StartDate was displayed the following was shown:
DSPLY 2023-12-31 |
In other words I was able to change the constant. I am not sure what I think of that. Part of me wanted this to error as a constant is, well, constant. And in my IMHO it should have caused an error. What do you think?
You can learn more about the Constant keyword when defining variables from the IBM website here.
This article was written for IBM i 7.5 TR4 and 7.4 TR10.
First of all thanks for that info, Simon.
ReplyDeleteOn the first look I cannot find a difference between DCL-S const and the current DCL-C, which is there for decades. Altering a const in debug is, from what I tried, not possible. Besides that you cannot explicitly define a length for the const, it's defined by its content.
The const on data-structures was long overdue, even though for reasons of completeness only. If it is really needed is questionable. As your example shows, working with a const instance of the original makes no sense at all, since it is empty and immutable. Non-const stuff we already have, so no need to comment further.
Altogether nothing but another gimmick by the compiler team that didn't cost much and we RPG developers still have to do many things by foot that are long provided by frameworks on other platforms.
Hey Simon, I was confused about this enhancement myself. I agree with you, in that it just doesn't make sense to me. Or maybe you (and I) have discovered a bug in the new enhancement? It sure seems like if you're going to be allowed to add the Const keyword to a variable, then you should get a runtime (or better yet, a compile time) error when you try to assign the variable a new value.
ReplyDeleteI think it should be valid to change the constant while in debug. The new constant feature is to prevent the RPG program from changing the value.
ReplyDeleteI agree in debug mode you should be able to change the constant (but not it any other circumstance).
ReplyDeleteIt sounds like the same behavior as a Const on a prototype parm. It's a compile time restriction. You can change the value in debug if you really want to.
ReplyDeleteRinger