Subroutine Parameters
A subroutine parameter lets the same subroutine perform its task on different inputs, with the caller choosing the input on each call.
Why a Fixed Subroutine Needs Inputs
Suppose you have written a subroutine that prints a line of output. Every time the program calls it, the same line appears. That is useful, but limited. Most useful subroutines need to know something about the situation they are working in: which number to display, which list to process, which label to attach to a result.
A subroutine parameter is the mechanism that supplies that information. The caller hands a value to the subroutine, and the subroutine uses that value while it does its job. A parameter is a value passed to a subroutine so that one fixed procedure can handle different inputs. The procedure stays the same. The value changes from call to call.
Many programming tasks are the same from one run to the next, but the details change each time. Printing a list of numbers is a good example. The act of printing never changes, yet which numbers appear depends on the situation. Rewriting the subroutine for every variation would be wasteful, so we give it a way to receive the details it needs at the moment it is called. This article introduces that mechanism through a problem we have already met: the 3N+1 sequence.
Tracing the 3N+1 Sequence by Hand
Recall the rule that generates a 3N+1 sequence. Begin with a number N. If N is odd, replace it with three times N plus one. If N is even, replace it with N divided by two. Keep applying this step until N becomes 1. Starting from N equal to 3, the steps produce 3, 10, 5, 16, 8, 4, 2, 1.
Now take the job we want a subroutine to do: print out such a sequence. The job itself is fixed. The subroutine always follows the same rule. What changes from call to call is the number the sequence begins with. Two different starting values produce two different printed lists, even though the procedure that produces them is identical.
Work through a second starting value by applying the rule step by step. Starting from 6, which is even, the next value is 3. Three is odd, so the next value is 3 times 3 plus 1, which is 10. From there the sequence continues 5, 16, 8, 4, 2, 1. Notice that the procedure never changed: only the first value you fed into it was different.
Reading the Parameter in a Function Header
The parameter is named in the subroutine's header, and that name is used inside the body. The header below is an illustration written for this article, not a listing from the source textbook. Its header names a parameter called n, and the body applies the 3N+1 rule to whatever value that name holds when the function runs. The function prints the whole sequence as a list, so the caller only has to supply the starting value.
[3, 10, 5, 16, 8, 4, 2, 1]
[6, 3, 10, 5, 16, 8, 4, 2, 1]- n in the header is the parameter: the name the subroutine uses for the value it receives
- The while loop is the fixed task: it never changes between calls
- Each call supplies a different starting value, so the printed list differs
Caller and Subroutine Exchanging a Value
It helps to separate two roles. The caller decides which starting value to use and hands it over. The subroutine receives that value and uses it to carry out the fixed procedure. Once the subroutine finishes its job, control returns to the caller, which continues with the rest of the program. The same subroutine can serve many different purposes, because the purpose is determined by what arrives rather than by a rewritten body.
Passing a Whole Array as One Parameter
A parameter does not have to hold a single number or a single word. Its type can be an array type. When that happens, the caller does not pass the array's elements one at a time. The entire array of values travels into the subroutine as a single parameter, and the subroutine has access to all of the values through that one parameter.
Consider a concrete need. Imagine a subroutine whose job is to display every value in an integer array in a neat format: the values separated by commas and wrapped in a pair of square brackets. The subroutine has to know which array to display. The way to tell it is to give the subroutine a parameter of type int[ ], the notation for an array of integers. The caller supplies the array when it makes the call, and the subroutine works on that array.
[4,7,2]- int[] values is the int[ ] parameter: one parameter standing for the whole array
- No comma is printed before the first value; a comma is printed before each later value
- Brackets wrap the whole list
The printing task has a precise formatting rule. A subroutine that prints an array neatly must handle the separators carefully: no comma before the first value, a comma before each later value, and brackets around the whole list. The loop in the example above follows exactly that rule, which is why the output has no leading comma and no trailing comma.
Mistakes When Reading Parameters
Common mistake Thinking the subroutine's body must be rewritten for each new input
What it looks likeWriting a separate print routine for starting value 3 and another for starting value 6
Why it failsThe fixed procedure is the same on every call. Only the value supplied by the caller changes.
Do this insteadWrite the procedure once with a parameter such as n, and pass different values at each call.
Common mistake Assuming the caller's variable and the parameter name are the same thing
What it looks likeCalling print_sequence(start) and then expecting the body to refer to start
Why it failsThe subroutine receives the value under its own name, which is n in the header.
Do this insteadUse the parameter name from the header inside the body, and remember the caller's name is separate.
Common mistake Passing an array as separate values when the parameter is int[ ]
What it looks likeExpecting printArray(4, 7, 2) to work when the header declares int[] values
Why it failsAn int[ ] parameter receives the whole array as one item.
Do this insteadCreate the array first, such as new int[] {4, 7, 2}, and pass that array as the single argument.
Practice: Predict the Printed Sequence
Using the print_sequence subroutine from earlier, what list does print_sequence(5) print? Apply the rule step by hand before you check.
Hints
- 5 is odd, so the next value is 3 times 5 plus 1
- Keep applying the rule until the value becomes 1
- The subroutine's body is unchanged; only the starting value differs
What do you think happens?
What list does print_sequence(5) print?
Reveal answer
[5, 16, 8, 4, 2, 1]
5 is odd, so it becomes 16. Then 16 is halved to 8, 8 to 4, 4 to 2, and 2 to 1, where the sequence stops.
Key Takeaways
- A parameter is a value passed to a subroutine so that one fixed procedure can handle different inputs.
- The caller chooses the input on each call, while the subroutine's task stays the same.
- Inside the subroutine, the parameter is referred to by its own name in the header, such as n.
- A parameter of type int[ ] receives an entire array as a single parameter rather than as separate values.
- Each subroutine is a subtask of a larger program, and designing how to split a program into subtasks is a separate skill.