fhg
Volume 11, Number 5 -- February 2, 2011

Another Reason Why Function Subprocedures Should Not Modify Their Parameters

Published: February 2, 2011

by Ted Holt

I've never liked the idea of functions modifying their parameters. It seems to me that a function should accept zero or more input values and return one and only one value. Modifying a parameter is a roundabout way of returning another value. While looking for something in the ILE RPG reference recently, I found yet one more reason why it's not a good idea for a function to modify a parm.

This is IBM's example code with my modifications to make it run.

Figure 189. Sample coding of a call with side effects 
 *..1....+....2....+....3....+....4....+....5....+....6....+....7...+....
H dftactgrp(*no) actgrp(*new)

D fn              PR             5P 0
D   parm                         5P 0

D A               S              5P 0
D X               S              5P 0

 *   A is a variable.  FN is procedure that modifies A.
 /free
     *inlr = *on;   
     a = 5;
     x = a + fn(a);
     return;
 /end-free
 
P fn              B
D fn              PI             5P 0
D   parm                         5P 0
 /free
     parm = parm + 1;
     return  2 * parm;
 /end-free
P fn              E

What's the value of X after the second EVAL?

The answer is: "I don't know." The answer may be 17 or 18, depending on whether the system calls the function before adding, or adds before calling the function. In IBM's words, "The order of evaluation within an expression is not guaranteed."

Little errors like this cause debugging nightmares. So what's the solution?

The solution is to return all values in modified parameters, like this:

H dftactgrp(*no) actgrp(*new)

D proc            PR
D   parm                         5P 0
D   answer                       5P 0

D A               S              5P 0
D X               S              5P 0

 *   A is a variable.  PROC is procedure that modifies A.
 /free
     *inlr = *on;
     a = 5;
     proc (a: x);
     x += a;
     return;
 /end-free

P proc            B
D proc            PI
D   parm                         5P 0
D   answer                       5P 0
 /free
     parm = parm + 1;
     answer = 2 * parm;
 /end-free
P proc            E

Now let's make it a bit more practical. Why would anybody make a function subprocedure modify a parameter? Maybe out of scope creep.

Suppose the original function takes a customer number and date as arguments and returns the total amount of sales for that customer on that date.

DCustSalesForDay  pr             9p 2
D   CustNbr                      6p 0 const
D   Date                         8p 0 const

D TotalSales      s              9P 2

/free
     // call the function subprocedure
     TotalSales = CustSalesForDay (CusNbr: DateOfSale);

... etc ...

PCustSalesForDay  b
D                 pi             9p 2
D   CustNbr                      6p 0 const
D   Date                         8p 0 const
D*** locals
D TotSls          s              9p 2
 /free
     setll (CustNbr: Date) slshistr;
     dow '1';
        reade (CustNbr: Date) slshistr;
        if %eof();
           leave;
        endif;
        TotSls += InvAmt;
     enddo;
     return TotSls;
 /end-free
P                 E

Later, someone requests that the number of sales also be printed on the report. Since we already have a routine that's accessing those database records, we may as well add another parameter for the count.

DCustSalesForDay  pr             9p 2
D   CustNbr                      6p 0 const
D   Date                         8p 0 const
D   NbrOfSales                   3P 0

D TotalSales      s              9P 2
D SalesCount      s              3P 0

/free
     TotalSales = CustSalesForDay (CusNbr: DateOfSale: SalesCount);

... etc ...
PCustSalesForDay  b
D                 pi             9p 2
D   CustNbr                      6p 0 const
D   Date                         8p 0 const
D   NbrOfSls                     3P 0
D*** locals
D TotSls          s              9p 2
 /free
     TotSls = *zero;
     NbrOfSls = *zero;
     setll (CustNbr: Date) slshistr;
     dow '1';
        reade (CustNbr: Date) slshistr;
        if %eof();
           leave;
        endif;
        TotSls += InvAmt;
        NbrOfSls += 1;
     enddo;
     return TotSls;
 /end-free
P                 E

But here's the better way:

DCustSalesForDay  pr
D   CustNbr                      6p 0 const
D   Date                         8p 0 const
D   AmtOfSales                   9P 2
D   NbrOfSales                   3P 0

D TotalSales      s              9P 2
D SalesCount      s              3P 0

/free
     CustSalesForDay (CusNbr: DateOfSale: TotalSales: SalesCount);

... etc ...
PCustSalesForDay  b
D                 pi
D   CustNbr                      6p 0 const
D   Date                         8p 0 const
D   AmtOfSales                   9P 2
D   NbrOfSales                   3P 0
 /free
     AmtOfSales = *zero;
     NbrOfSales = *zero;
     setll (CustNbr: Date) slshistr;
     dow '1';
        reade (CustNbr: Date) slshistr;
        if %eof();
           leave;
        endif;
        AmtOfSales += InvAmt;
        NbrOfSales += 1;
     enddo;
 /end-free
P                 E

There are exceptions to this principle. For example, we've published two articles dealing with I/O routines that return one value and modify another. I've referenced them below.

To see the RPG manual page that gave rise to this tip, visit the IBM i Information Center.


RELATED STORIES

Returning a Pointer to a Data Structure from a Function

Functions Can Modify Parameters, Too



                     Post this story to del.icio.us
               Post this story to Digg
    Post this story to Slashdot


Sponsored By
SEQUEL SOFTWARE


On Thursday, February 10, the beauty of using
SEQUEL for IBM i data access and analysis will become clear.

In an hour-long, action-packed Webinar, SEQUEL for Developers,
we'll demonstrate 10 tips that help you deliver the information
your end users need in formats they want.

It's time to stop struggling with complicated data access solutions.

Follow this link to learn more!



Senior Technical Editor: Ted Holt
Technical Editor: Joe Hertvik
Contributing Technical Editors: Edwin Earley, Brian Kelly, Michael Sansoterra
Publisher and Advertising Director: Jenny Thomas
Advertising Sales Representative: Kim Reed
Contact the Editors: To contact anyone on the IT Jungle Team
Go to our contacts page and send us a message.

Sponsored Links

PowerTech:  Schedule a FREE IBM i Compliance Assessment!
Vision Solutions:  The State of Resilience 2010. Download the report now!
Four Hundred Monitor Calendar:  Latest info on national conferences, local events, & Webinars


 

IT Jungle Store Top Book Picks

BACK IN STOCK: Easy Steps to Internet Programming for System i: List Price, $49.95

The iSeries Express Web Implementer's Guide: List Price, $49.95
The iSeries Pocket Database Guide: List Price, $59
The iSeries Pocket SQL Guide: List Price, $59
The iSeries Pocket WebFacing Primer: List Price, $39
Migrating to WebSphere Express for iSeries: List Price, $49
Getting Started with WebSphere Express for iSeries: List Price, $49
The All-Everything Operating System: List Price, $35
The Best Joomla! Tutorial Ever!: List Price, $19.95


 
The Four Hundred
Notes/Domino: Less Platform Talk, More Programming Action

IBM Trumpets LotusLive Successes, New App Partnerships

RPG Surges in Popularity, According to Language Index

Mad Dog 21/21: The So-Called Network

Palmisano Rakes in $9 Million for IBM's 2010 Performance

Four Hundred Stuff
Magic to Sell MicroStrategy BI into IBM i Base

Info Builders Shrinks BI Apps with InfoMini

Mobility, the Cloud, and Social Business Top Lotusphere Agenda

Oracle Touts JDE EnterpriseOne Growth

m-Power Graphing Feature Gets an Overhaul

Four Hundred Monitor
Four Hundred Monitor's
Full iSeries Events Calendar

System i PTF Guide
September 25, 2010: Volume 12, Number 39

September 18, 2010: Volume 12, Number 38

September 11, 2010: Volume 12, Number 37

September 4, 2010: Volume 12, Number 36

August 28, 2010: Volume 12, Number 35

August 21, 2010: Volume 12, Number 34

TPM at The Register
ARM Holdings eager for PC and server expansion

VMware Go promoted to Pro

Intel shakes off $1bn chipset flaw

Intel finds flaw in Sandy Bridge chipset

VMware creates private clouds for newbies

Verizon borgs Terremark for $1.4bn

Mellanox itching to close Voltaire, crank up InfiniBand

Deliveries for final Apple Xserves stalled to April

Xen sends Citrix Q4 into the clouds

Dell talks shopping in Davos

Cisco borgs network 'guardian angel'

Robust network spending drives Juniper's Q4

THIS ISSUE SPONSORED BY:

Botz & Associates, Inc.
SEQUEL Software
System i Developer


Printer Friendly Version


TABLE OF CONTENTS
Synchronize Your Outlook Calendar with DB2 for i ERP Data

Another Reason Why Function Subprocedures Should Not Modify Their Parameters

Admin Alert: QPWDRULES Rules!!! Opening Up User Password Options with i 6.1

Four Hundred Guru

BACK ISSUES




 
Subscription Information:
You can unsubscribe, change your email address, or sign up for any of IT Jungle's free e-newsletters through our Web site at http://www.itjungle.com/sub/subscribe.html.

Copyright © 1996-2011 Guild Companies, Inc. All Rights Reserved.
Guild Companies, Inc., 50 Park Terrace East, Suite 8F, New York, NY 10034

Privacy Statement