An Indicator By Any Other Name
August 24, 2011 Jon Paris
Because indicators have been around forever, we kind of take them for granted. I often find that RPGers don’t really understand all the ways in which they can be used. This tip is an attempt to highlight four things that every RPGer should know about our little friends.
1. Indicators, or at least the standard set, are an array.
You may not need to use indicators *In01 – *In99 as an array, but the fact that they are an array offers an opportunity to name them with minimal effort.
I have always hated the fact that we have to rely on numbered indicators for display and printer files. The folks in Rochester have never given us an option to associate a name with them, which could work quite nicely with a variant of RPG’s INDDS() keyword.
But there is an easy way in which you can associate an indicator with a name without having to use pointers to re-map the *In indicators. It takes advantage of the fact that *In01 is equivalent (i.e., it points to exactly the same byte in memory) as *In(01).
Assume for a moment that *In25 is used to indicate that an account is valid. So rather than use the number 25, if we set up a named constant called validAccount and give it a value of 25, we can then refer to *In(validAccount) and everyone who subsequently reads our code will have a much easier time of it. Like this:
d validAccount c 25 /Free If *In(validAccount); // Process account charges EndIf;
In fact, these days I go one step further and use a naming convention suggested to me by my friend, Aaron Bartell, to add the actual indicator number to the end of the name like so: *In(validAccount_25). Now anyone who reads my code not only knows the purpose of the indicator, but also knows which indicator to look for in the DDS. The resulting code looks like this:
d validAccount_25... d c 25 /Free If *In(validAccount_25); // Process account charges EndIf;
2. RPG understands indicators. You don’t need to spell everything out.
Right from its inception, RPG has understood indicators to be boolean variables that simply equate to true or false. So If *In25 = ‘1’; is not only ugly–it is a waste of typing because the shorter and, to me at least, more obvious If *In25; is identical in effect.
Now, of course, if you haven’t taken point 1 to heart, the benefit (other than less typing) may not be that apparent to you. But if we are being good little programmers and naming our indicators, I think you will agree that:
Are a lot easier to understand then:
If validAccount = '1';
To me, the increased readability shines though when you consider the negative condition. For example consider how much more obvious:
If Not validAccount;
Is when compared with:
If validAccount = '0';
Perhaps you never use ‘1’ but use the figurative constants *On and *Off? Isn’t that better? Not a lot really. Although most of us have grown up thinking of indicators as being “On” or “Off”, that is a just throwback to the tabulator origins of RPG, where indicators were real physical switches that could indeed be on or off. I won’t bore you with a dissertation of the correlation of tabulators and RPG–just trust me on that one.
3. You can assign the results of logical expressions to indicators.
This is one that most people don’t realize. If I include it in a presentation code sample, the inevitable question is “What release was that added in?” The answer is that it has always been there. From the very start of RPG IV the following has been valid syntax, and one that I have often found useful for setting that “If there are errors flash this message” indicator. Something like this:
*IN90 = *IN80 or *IN81 or *IN82 ;
Which simply means: Set indicator 90 to true if any of indicators 80, 81,or 82 are true.
It looks even better when we name the indicators:
*In(errorFound) = *In(invalidAccount) or *In(invalidProduct) or . . .
This ability is not restricted to indicator expressions. For example the following is perfectly valid, and, in my opinion, has an elegant simplicity:
d overdueBalance_40... d c 40 /Free // Set print control indicator 40 if payment overdue *In(overdueBalance_40) = ( %Date() > dueDate );
4. If a subprocedure returns an indicator, you can use it as a simple boolean.
For example, suppose we have a subprocedure that returns an indicator that is true if a transaction is valid. In essence it might look something like this:
p ValidTransaction... p b d pi n d accountNo 5s 0 d transData LikeDS(transDetails) d validTrans s n inz /free // Perform assorted validation tasks and set validTrans true // if the transaction is valid Return validTrans; /End-free p ValidTransaction... p e
Since the subprocedure returns an indicator value, we can use it like this:
If ValidTransaction( accountNo : transDetails ); // process transaction Else; // issue error message etc. EndIf;
A knowledge of the way indicators work in RPG IV can make your programming life easier, and your programs easier to understand for those that come after you.
Jon Paris is one of the world’s most knowledgeable experts on programming on the System i platform. Paris cut his teeth on the System/38 way back when, and in 1987 he joined IBM’s Toronto software lab to work on the COBOL compilers for the System/38 and System/36. He also worked on the creation of the COBOL/400 compilers for the original AS/400s back in 1988, and was one of the key developers behind RPG IV and the CODE/400 development tool. In 1998, he left IBM to start his own education and training firm, a job he does to this day with his wife, Susan Gantner–also an expert in System i programming. Paris and Gantner, along with Paul Tuohy and Skip Marchesani, are co-founders of System i Developer, which hosts the new RPG & DB2 Summit conference. Send your questions or comments for Jon to Ted Holt via the IT Jungle Contact page.