Skip to content
ExamSpine

Lesson 4.6

Functions that call your functions

Part 4: FunctionsReading, about 6 min3 exercises in this lesson

Java answers can't run on Spine yet. You can still read Java, trace it, and put an answer's lines in order.

Functions that call your functions

By the end of this you will be able to write a small helper function, call it from inside another function you wrote, and follow a program as it goes from one call to the next.

So far, your functions were called from the main code. A function can also call another function that you wrote. This lets you solve a small job once, in a helper function, and then use that helper wherever a bigger job needs it.

A function that calls a helper

def square(n):
    return n * n

def sum_of_squares(a, b):
    return square(a) + square(b)

print(sum_of_squares(3, 4))
public static void main(String[] args) {
    System.out.println(sumOfSquares(3, 4));
}

static int square(int n) {
    return n * n;
}

static int sumOfSquares(int a, int b) {
    return square(a) + square(b);
}

This prints 25. Here is what happens, in order, after the main code calls the function that adds the squares, with 3 and 4.

  1. That function starts, with a holding 3 and b holding 4.
  2. It reaches the first call to square. It waits there while square runs with n holding 3. square returns 9.
  3. It reaches the second call. square runs again, this time with n holding 4, and returns 16.
  4. It adds 9 and 16 and returns 25 to the main code, which prints it.

Each function waits for the call it made to finish, then carries on from the same place, with the returned value standing where the call was. A call to your own function works the same way whether it comes from the main code or from inside another function.

In Python, the helper may be defined above or below the function that calls it. What matters is that both def lines have run before the first call runs, which is why the call from the main code comes last. In Java, the methods can be in any order.

A helper inside a loop

A helper can also be called on every turn of a loop. This program counts how many whole numbers divide 12 with no remainder.

def divides(d, n):
    return n % d == 0

def count_divisors(n):
    count = 0
    for d in range(1, n + 1):
        if divides(d, n):
            count = count + 1
    return count

print(count_divisors(12))
public static void main(String[] args) {
    System.out.println(countDivisors(12));
}

static boolean divides(int d, int n) {
    return n % d == 0;
}

static int countDivisors(int n) {
    int count = 0;
    for (int d = 1; d <= n; d++) {
        if (divides(d, n)) {
            count = count + 1;
        }
    }
    return count;
}

The helper returns true or false, so a call to it can be the condition of an if. The loop tries every d from 1 to 12, and the helper says yes for 1, 2, 3, 4, 6 and 12. So this prints 6.

The order of the values matters here as well. Asking the helper about 3 and 12, in that order, asks whether 3 divides 12, which is true. Asking about 12 and 3 asks whether 12 divides 3, which is false.

Why build from helpers

  • Each helper can be checked on its own. Call square with 3 and see 9 before you use it anywhere else. If the bigger function goes wrong later, you already know the helper is not the cause.
  • The bigger function reads like its plan. A line that adds the square of a to the square of b says what it does.
  • A helper written once can be used many times: square is called twice above, and divides once on every turn of the loop. A fix to the helper fixes every place that uses it.

Two common slips

  • Calling a helper and dropping its value. A line with only a call to square on it, such as square(a), runs the helper, but the value it returns is thrown away. This gives no error in either language, and nothing is kept. Store the value, use it in a bigger expression, or return it.
  • Giving a helper its values in the wrong order. If the loop asked the helper about n and d instead of d and n, it would check whether n divides each d. With n as 12, that is true only when d is 12, so the count would be 1. Both values are whole numbers, so no error points to the slip.

Now try it yourself on the questions below.

Exercise 4.6.14.6.1 · Write itLargest of three

Write a function that returns the largest of three whole numbers.

  1. a, b and c are whole numbers that can be negative.
  2. Two or all three may be equal. If the largest value appears more than once, return it.

Write a helper function that returns the larger of two numbers, and use it.

Only the number your function returns is checked.

def max_of_three(a: int, b: int, c: int) -> int

You cannot use these in this question:

  • max()
  • min()
  • sorted()

This question is about writing the comparison yourself, so built-in max functions are not allowed.

Examples

Your function is tested on 7 cases: the 3 examples below, and 4 hidden ones that check the rules above.

  • max_of_three(1, 2, 3) should return 3: the third is largest (rule 1)
  • max_of_three(5, 5, 5) should return 5: all three equal (rule 2)
  • max_of_three(9, 3, 7) should return 9: the first is largest (rule 1)

public static int maxOfThree(int a, int b, int c)

Checking whether Java answers can run here.

You cannot use these in this question:

  • Math.max()
  • Math.min()
  • Collections.max()
  • Collections.min()

This question is about writing the comparison yourself, so built-in max functions are not allowed.

Examples

Your function is tested on 7 cases: the 3 examples below, and 4 hidden ones that check the rules above.

  • maxOfThree(1, 2, 3) should return 3: the third is largest (rule 1)
  • maxOfThree(5, 5, 5) should return 5: all three equal (rule 2)
  • maxOfThree(9, 3, 7) should return 9: the first is largest (rule 1)
solution.pySolution.java

Exercise 4.6.24.6.2 · Write itSum of digits

Write a function that returns the sum of the digits of a whole number.

  1. n is a whole number from 0 to 999999999.
  2. The sum of the digits of 0 is 0.

Write helper functions for "last digit" (the remainder when dividing by 10) and "remove last digit" (whole-number division by 10), and use them. Do not convert the number to text.

Only the number your function returns is checked.

def sum_of_digits(n: int) -> int

You cannot use these in this question:

  • str()
  • len()
  • repr()
  • format()
  • list()
  • import math

This question is about using arithmetic to extract digits, so converting to text is not allowed.

Examples

Your function is tested on 7 cases: the 3 examples below, and 4 hidden ones that check the rules above.

  • sum_of_digits(123) should return 6: 1 + 2 + 3 = 6 (rule 1)
  • sum_of_digits(0) should return 0: zero has a digit sum of 0 (rule 2)
  • sum_of_digits(9) should return 9: a single digit (rule 1)

public static int sumOfDigits(int n)

Checking whether Java answers can run here.

You cannot use these in this question:

  • String.valueOf()
  • Integer.toString()
  • .length()
  • .toCharArray()
  • .charAt()
  • .chars()

This question is about using arithmetic to extract digits, so converting to text is not allowed.

Examples

Your function is tested on 7 cases: the 3 examples below, and 4 hidden ones that check the rules above.

  • sumOfDigits(123) should return 6: 1 + 2 + 3 = 6 (rule 1)
  • sumOfDigits(0) should return 0: zero has a digit sum of 0 (rule 2)
  • sumOfDigits(9) should return 9: a single digit (rule 1)
solution.pySolution.java

Exercise 4.6.34.6.3 · Answer itWhy decompose

A student writes one 40-line function. It reads three test marks typed by the user, works out their average, decides a grade letter from the average, and prints a short report.

(a) Explain one problem with keeping all of this in a single function. [1]

(b) Name two smaller functions you would split it into, saying what each one does. [1]

(c) Explain how one of your two functions could be tested on its own, without running the rest of the program. [1]

[3]