For many subprocedures, I only need to return a single value. It might be a number, a character, string or an array of the same type. Although a data structure is also considered to be a single value for return purposes, I discuss data structure returns in more detail in Subprocedure Returns, part 2. In this article, I'll simply show a subprocedure prototype that returns a simple value. There really is not a lot to say.
The sample code is from my STRING module. The subprocedure
prototype shown here is used to convert an input value to a corresponding
hexadecimal string representation, suitable for printing or display. For
example, if I call the subprocedure with the string value "A",
I will get the string value "C1" returned, its EBCDIC
hexadecimal representation.
****************************************************************
* Procedure STRING_convertToHexString
*
* Convert an input character string to its equivalent
* hexadecimal string representation.
* (EBDCIC)
*
* Example:
* Input string: AB12 Returned: x'C1C2F1F2'
*
* Parameters
*
* inputString - the input string to convert. Maximum
* length 512.
*
* Returns
*
* hexString - the hexadecimal representation of the
* input string
****************************************************************
D STRING_convertToHexString...
D pr like(Types.VARYING1024)
D inputString...
D like(Types.VARYING512)
D const
The subprocedure accepts one required parameter, inputString.
After some thought, I assigned a maximum length of 512 to the input parameter.
Because each byte in the input string will be converted to two bytes (two hex digits), I defined a return value exactly twice the
length of the input parameter.
I actually had quite a time with the parameter definition, in terms of using
a VARYING data type. The IBM ILE RPG Reference manual seems to
encourage its use, as in this excerpt from the V5R2 manual:
Why You Should Use Variable-Length Fields: Using variable-length fields for temporary variables can improve the performance of string operations, as well as making your code easier to read since you do not have to save the current length of the field in another variable for %SUBST, or use %TRIM to ignore the extra blanks.
If a subprocedure is meant to handle string data of different lengths, using variable-length fields for parameters and return values of prototyped procedures can enhance both the performance and readability of your calls and your procedures. You will not need to pass any length parameters or use CEEDOD within your subrocedure (sic) to get the actual length of the parameter.
Given the recommendation, I wondered if I should code the subprocedure with
the maximum length allowed. Since the maximum length of a character field is
65,535, I would have to make the input parameter 1 byte less than half of that,
rounded down. This is one of the very few times when I am concerned about the
compiled code, in terms of performance. In this case, I am unsure about how much
memory the subprocedure requests at run-time. The value of using the VARYING
data type is that it makes it easier to work with the data, but I don't want to
set aside 65,535 bytes of memory when most of the time I will be converting 132
bytes or less. The performance issue I am concerned with is more an issue of
resource usage, rather than processor usage. If I were to needlessly allocate
thousands more bytes than needed, I would put my program in worse shape, in
terms of its potential for being swapped out. If I later find out that there are
no negative concerns with maximum length varying fields, I will probably have to
create another subprocedure to handle the longer parameter, as the current
subprocedure will already be in production.
The return value is simply defined on the subprocedure prototype (pr)
statement, as it will also be on the procedure interface (pi)
statement.
Both the parameter and the return value are defined using like-defines, using
field definitions in the Types data structure. I will describe this
technique in more detail in a future article. For now, the code in the Types
data structure looks like this:
DTypes ds qualified
D based(ptrNull)
D VARYING512 512 varying
D VARYING1024 1024 varying
I also have subprocedures that don't return any value. These are somewhat unusual, as the point of calling a subprocedure is usually to affect something of interest for subsequent use. But there are times when I have subprocedures that I simply call, expecting nothing in return. In that case, there is nothing to define on the prototype and procedure interface statements.
Craig Pelkie
December 13, 2004
Copyright © 2004, 2005, Craig Pelkie, ALL RIGHTS RESERVED