Can a Function Return More Than One Value?
January 20, 2010 Hey, Ted
Is it possible for an RPG subprocedure to return more than one value? (I assume it isn’t; the RETURN opcode only allows for one argument.) I want to write a function subprocedure that will return a data structure of information taken from various database files. However, the subprocedure will also need to return a status code to indicate whether or not the I/O was successful. Do you have any suggestions?
What you want to do is something like this:
eval (MyDataStructure: Status) = GetData (KeyValue)
No, that won’t work. But I can show you two other ways that will.
Let’s set up a situation like the one you’re describing. Suppose a service program needs a subprocedure GetCustInfo to provide customer data to its caller. It also needs to tell the caller whether the data retrieval succeeded or not.
One way to handle this is to return both values in parameters. GetCustInfo uses the values in Company and Customer to retrieve the data, then modifies CustRec and FileStatus accordingly. The subprocedure behaves as a subroutine, not as a function, and any RETURN opcodes in the subprocedure do not have arguments.
P GetCustInfo b D pi D inCompany 3p 0 value D inCustomer 5p 0 value D ouCustRec likeds(CustRec) D ouStatus 1p 0 D D CustKey ds likerec(Customer: *key) /free CustKey.CompanyNo = inCompany; CustKey.CustomerNo = inCustomer; monitor; chain %kds(CustKey) Customer ouCustRec; if %found(); ouStatus = *zero; else; ouStatus = 1; endif; on-error; ouStatus = 2; endmon; return; /end-free P e
Use CALLP to invoke GetCustInfo.
D Company s 3p 0 D Customer s 5p 0 D FileStatus s 1p 0 D CustRec ds likerec(Customer: *input) inz /free callp GetCustInfo (Company: Customer: CustRec: FileStatus);
If you prefer, you can use a function subprocedure that modifies a parameter. The function passes two values–a status code and a data structure–to the caller through two mechanisms, so which mechanism should you pair with which value?
I prefer to pass data through the modified parameter and let the function return the status.
P GetCustInfo b D pi 1p 0 D inCompany 3p 0 value D inCustomer 5p 0 value D ouCustRec likeds(CustRec) D D CustKey ds likerec(Customer: *key) /free CustKey.CompanyNo = inCompany; CustKey.CustomerNo = inCustomer; monitor; chain %kds(CustKey) Customer ouCustRec; if %found(); return *zero; else; return 1; endif; on-error; return 2; endmon; /end-free P e
For one thing, status codes tend to be small and data structures tend to be bigger. But an even greater advantage is that the function calls work well with control structures. For instance:
dow GetCustInfo(Company: Customer: CustRec) = *zero;
As a rule, functions do not modify parameters. After all, can you think of an RPG built-in function that modifies an argument? But that’s not to say that a function should never modify a parameter. Your application is a good example of that.