COBOL has many mechanisms for passing parameters to subroutines, including the CALL statement, invocation of object-oriented methods, intrinsic functions, etc...
However, in most COBOL programs the principal means of invoking a subroutine is via the PERFORM statement, and until now, this has not offered any way of passing parameters. Instead, information is often passed to the subroutine by setting the value of a working-storage item before the PERFORM, and then picking it up from that working-storage item within the performed procedure, as in this example:
01 temp-num binary-long. ... move 3 to temp-num. perform display-it. ... display-it section. display temp-num. ...
The disadvantage with this is that there is no locality of reference: whatever performs the first section may not be expecting the value of temp-num to change, resulting in unexpected behavior. It is also never explicit what the performed procedure expects before it is invoked, which again can lead to unexpected behavior if some required input is not already set.
Parameterized sections overcomes such issues by providing data locality within a section of a program. The previous example can now be coded in such a way that no working-storage items need to be modified:
perform display-it(3). ... display-it section (num-param as binary-long). display num-param.
Using this syntax, the display-it section must be performed by passing it a parameter (and a compilation error will result if the parameter is omitted).
You can make the parameter optional by specifying a default value within the section header. The following example displays 99 when no other value is passed, as it is the default value for the section parameter:
perform display-it(). ... display-it section (num-param as binary-long = 99). display num-param.
Parameterized sections can also return a value, as in this example:
01 i1 binary-long value 3. 01 i2 binary-long value 4. 01 i3 binary-long. ... perform addvars (i1, i2) returning i3. display i3. goback. addvars section(p1 as binary-long, p2 as binary-long) returning res as binary-long. add p1 p2 giving res.
It is even possible to refer to such a section (i.e. one that has a returning phrase) using functional syntax, as shown with the display statement below:
01 i1 binary-long value 3. 01 i2 binary-long value 4. ... display addvars(i1, i2). goback. addvars section (p1 as binary-long, p2 as binary-long) returning res as binary-long. add p1 p2 giving res.
01 i1 binary-long value 1. Procedure division. Perform s1(i1) Goback. S1 section (i1 as binary-long) Display i1. Declare i1 as binary-short. *> this would generate an error Perform varying i1 as binary-long from 1 by 1 until i1 > 100 *> Invalid display i1 end-perform. Perform varying i2 as binary-long from 1 by 1 until i2 > 100 *> Valid display i2 end-perform. Perform varying i2 as binary-long from 1 by 1 until i2 > 100 *> Valid, as previous i2 no longer in scope display i2 end-perform.
The DECLARE statement was originally introduced in the context of .NET COBOL. More recently, the statement also supports native COBOL code. However, in previous native COBOL code, such variables were effectively appended to the LOCAL-STORAGE section, which meant that they did not operate as expected in a recursive context. This old behavior is still available using the Compiler's DECLARE"1" directive; however, using the new default behaviour, locally declared variables are allocated afresh each time a section is entered.
The following example demonstrates this using a simple routine for calculating the n'th Fibonacci number.
s1 section(n1 as binary-long) returning ret as binary-long. if n1 <= 1 set ret to n1 exit section end-if declare left-side as binary-long = s1(n1 - 1) declare right-side as binary-long = s1(n1 - 2) compute ret = left-side + right-side *> another alternative to the above three lines could be: *> compute ret = s1(n1 - 1) + s1(n1 - 2)
More examples on using parameterized sections can be found in the Parameterized Sections (examples) topic.