As we can see from our IsWorkday example, an internal procedure is very similar to a subroutine. One of the advantages it has over a subroutine is the use of local variables - which may be coded within a procedure without the fear of conflicting with fields in the mainline code.
Another advantage which we haven't talked about yet is the automatic type-casting of parameters.
When a subroutine is called, it relies on certain fields being set correctly prior to it's execution. For example, if we were to code the IsWorkday procedure as a subroutine, we would create a common field name for the date to be tested. Each time we executed the subroutine, we would first need to make sure to move the date we want to test to this field.
If we created IsWorkday as a separate program rather than a subroutine or procedure, we would need to call the program by passing parameters. If you are familiar with how parameters are passed between programs, you know that the value of the parameter is not actually passed. Rather an address pointer is passed that points to the memory location of the field in the calling program. When the called program refers to or changes the parameter, it is actually referring to or changing the field from the program where it was called. This type of parameter passing is called pass by reference.
ILE procedures pass parameters by reference as well, but with one key exception. If the parameters are the same general type as expected (alpha, numeric, date, etc.) but differ in their attributes (length, packed vs. zoned, *iso vs. *usa), the attributes will automatically be converted (casted).
For example, lets assume we have a procedure that accepts a 7-digit packed numeric field as a parameter. If we call the procedure with a 5-digit zoned field, a conversion will automatically occur to make the procedure call work correctly. If you had this attributed mis-match when calling a separate program rather than a procedure, you would get a decimal-data error.
Several important points about procedure parameter typecasting:
Note that in the IsWorkday procedure we coded the date field parameter with DATFMT(*iso). We can safely call the procedure with a date of a different format and the conversion will occur automatically.
If, however, we would have specified a DATFMT(*ymd) (or any data format with a two-digit year), and tried to call the procedure with a 4-digit year date format outside the valid range for a 2-digit year (January 1, 1940 to December 31, 2039) we would get a run-time exception.
This brings up a good point. Procedures should always be coded to be as flexible as reasonably possible, requiring as little work as possible from the end-user programmer, and as bullet-proof as possible. As we begin to use more advanced procedure techniques, it will be more challenging to debug problems than if they were in the mainline code.
Looking at our IsWorkday example, we may find that passing a parameter of a date-type field may not be convenient. Most of the dates we test may be in a 6 or 8-digit numeric field. To use the procedure as it is now, we will always need to convert the numeric field to a date-type field, and then call the procedure. Also, recall that before we move a number to a date-field, we should test it first for a valid date.
This means that everytime before we use the procedure (assuming our dates are in a numeric format) we need to (1) setup a temporary date field in D-specs, (2) test the numeric date for validity, (3) evaluate the result of the test, and (4) move the number to a date field. All this preliminary work contradicts our statement about making procedure as easy to use as possible.
Therefore, lets take advantage of automatic typecasting and change our procedure to be more user friendly.
Changing IsWorkday to accept a numeric parameter
We are now going to change IsWorkday so that instead of forcing the calling code to convert numeric dates to a date-type field, it will accept a numeric field and do the conversion for you.
Lets look at the new procedure interface to allow this:
Don't forget to also change the prototype similarly
Note that we are accepting an 8-digit date. Because of typecasting, it will also automatically accepts 6-digit dates also. We also need to setup a local variable in the procedure for the converted date:
We will now test the numeric parameter for a valid date format. We are going to assume that the date is passed either in CCYYMMDD or YYMMDD formats. If your application system has mixed date formats in it, you can either write another procedure to convert dates between formats, or accepts a second parameter of the date format being passed.
If an invalid date was passed, the built-in-function %ERROR will return a value of true, and we want to return a value a boolean value of false (*off) because the date is not a workday. Otherwise, we want to move the numeric date to a date-type data field, and test it as we did before.
With the procedure written like this, we can now test either 6 or 8-digit dates without having to first convert them to a date-type field:
Send mail to firstname.lastname@example.org
with questions or comments about this web site.
Last Modified: August 30, 2000