Writing Your First Subroutine
A parameter is a value passed to a subroutine so that one fixed procedure can handle different inputs.
Why a Fixed Procedure Needs Varying Input
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. A subroutine that performs such a task would be wasteful if it had to be rewritten for every variation of the numbers. Instead, we give it a way to receive the details it needs at the moment it is called.
The mechanism for doing this is the parameter. A parameter is a value passed to a subroutine so that one fixed procedure can handle different inputs. In this article we introduce parameters through a problem we have already met: the 3N+1 sequence. Before you see any code, try to hold two questions in mind. What part of the job stays the same every time the subroutine runs? What part could be different on each call?
Recalling the 3N+1 Rule
The 3N+1 sequence is generated by a rule that begins with a number N. If N is odd, it is replaced with three times N plus one. If N is even, it is replaced with N divided by two. The step is applied again and again until N becomes 1.
Generating the sequence from a starting value of 3
Apply the 3N+1 rule starting from N equal to 3 and list every value produced until N reaches 1.
- 1Start
N is 3, which is odd, so the next value is 3 times 3 plus 1, which is 10.
- 2Second step
N is 10, which is even, so the next value is 10 divided by 2, which is 5.
- 3Third step
N is 5, which is odd, so the next value is 3 times 5 plus 1, which is 16.
- 4Remaining steps
From 16 the values are 8, 4, 2, and finally 1, where the process stops.
The full sequence is 3, 10, 5, 16, 8, 4, 2, 1.
Tracing a Starting Value Through the Subroutine
Now imagine the job we want a subroutine to do: print out a 3N+1 sequence. The job itself is fixed. The subroutine always prints a 3N+1 sequence, and it always follows the same rule. What changes from call to call is the number the sequence begins with. The caller decides which starting value to use and hands it over. The subroutine receives that value under a name of its own, which is the parameter, and uses it to carry out the fixed procedure.
Read the diagram from left to right. The caller supplies a value. That value enters the subroutine as the parameter n. The fixed rule then runs on whatever n holds, and the printed sequence is the result. The number 3 determines where the chain of values begins, and the rule determines everything after that.
What do you think happens?
Suppose the caller passes 6 instead of 3. Before reading on, predict the first value that gets printed and the full list.
Reveal answer
The printed list is 6, 3, 10, 5, 16, 8, 4, 2, 1.
The subroutine prints the starting value first. Since 6 is even, the next value is 6 divided by 2, which is 3. From 3 the rule continues exactly as it did in the earlier example, producing 10, 5, 16, 8, 4, 2, 1.
The Parameter as a Named Entry Point
A subroutine's header names its parameter, and the body refers to that name. Whatever value the caller passes is what the name holds when the subroutine runs. The sketch below is an illustration written for this article. It is not the listing from the source textbook, which does not reproduce the subroutine code in the passage we are working from. It shows the idea in Python: the header names a parameter called n, and the body applies the 3N+1 rule to whatever value that name holds.
def print_sequence(n):
while n != 1:
print(n)
if n % 2 == 1:
n = 3 * n + 1
else:
n = n // 2
print(n)
print_sequence(3)- 1def
print_sequence(n): declares the subroutine and names its single parameter n. - 2while n != 1: repeats the body until the current value reaches 1.
- 3
print(n)outputs the current value before it is changed. - 4if n % 2 == 1 tests whether n is odd; the branch then applies three times n plus one, or else halves n.
- 5
print(n)after the loop displays the final 1. - 6
print_sequence(3)is the call: the caller passes 3, which the subroutine receives as n.
- The name n in the header is the parameter that receives the caller's value.
- The while loop applies the fixed 3N+1 rule and stops when n reaches 1.
- The final print displays the 1 that ends the sequence.
3
10
5
16
8
4
2
13
10
5
16
8
4
2
1Same Procedure, Different Results
Two calls with different starting values produce two different printed lists, even though the procedure that produces them is identical. The diagram below places the two calls side by side. Both columns use the same subroutine body. Only the starting value differs.
The two lists differ only at the start. The call with 6 prints 6 first, then continues into the same run of values that the call with 3 reaches after its first step. The body of the subroutine did not change between the two calls. The starting value arriving at the parameter did.
Mistakes Beginners Make with Parameters
Common mistake Rewriting the subroutine body for each new starting value
What it looks likeWriting one routine that prints the sequence for 3, another for 6, and another for 5.
Why it failsThe task is the same each time. Only the starting value varies, so separate copies duplicate the same rule.
Do this insteadWrite one subroutine with a parameter, and let each caller pass the value it needs.
Common mistake Assuming the parameter is the caller's variable
What it looks likeExpecting the subroutine to change a variable named start in the caller just because the parameter is named n inside the subroutine.
Why it failsThe subroutine receives the value under a name of its own. The name n is local to the subroutine.
Do this insteadThink of the parameter as receiving a value, and use the caller's variables only as the source of that value.
Common mistake Treating the fixed rule as something the caller supplies
Why it failsThe caller supplies the varying input. The procedure, here the 3N+1 rule, stays inside the subroutine.
Practice Tracing a New Call
Using the print_sequence subroutine described in this article, trace the output of the call print_sequence(5). Write each value that gets printed, in order.
Hints
- The subroutine prints the starting value first.
- Check whether 5 is odd or even, then apply the matching step.
- Keep applying the rule until the value becomes 1, then remember that the final 1 is printed too.
Key Takeaways
- A parameter is a value passed to a subroutine so that one fixed procedure can handle different inputs.
- The caller supplies the varying starting value, and the subroutine receives it under its own parameter name.
- In the 3N+1 example, the printing task and the rule stay the same while the starting value changes from call to call.
- Parameters let one subroutine produce many different results without rewriting its body.