Writing functions

def, calling, and why subprograms help.

F4.1Functions and structured codeGCSE12 min

Do this lesson in the simulator

You have been calling functions since lesson F1.3: print, forward, distance. Now you write your own. A function is a named block of code you can run whenever you like, as often as you like, by calling its name. Exams call it a subprogram.

Defining a function

# the two lines every program starts with: the commands, then the robot
from bugbot import *
connect()

def report():
    x, y = position()
    print(f"at x={x} y={y}, wall in {distance()} cm")

report()
forward(60, distance=20)
report()

Run this in the simulator

def report(): defines a function called report. The indented block is its body, and nothing in it runs yet. Defining is like writing a recipe: nothing is cooked. report() calls it, and only then does the body run. Here it is called twice, so the report prints twice, and you wrote it once.

Define first, then call

Python reads a program top to bottom, so a function must be defined before the line that calls it runs:

# the two lines every program starts with: the commands, then the robot
from bugbot import *
connect()

signal()

def signal():
    led("red")
    tone(880, 0.2)
    led("off")

Run this in the simulator

NameError: name 'signal' is not defined. Move the call below the def and run again. This is why programs usually put all their functions near the top, and the main steps underneath.

What happens when a function is called

# the two lines every program starts with: the commands, then the robot
from bugbot import *
connect()

def signal():
    print("  signal starts")
    led("red")
    tone(880, 0.2)
    led("off")
    print("  signal ends")

print("before")
signal()
print("between")
signal()
print("after")

Run this in the simulator

Watch the order of the lines in the console. At each call, the program jumps into the function, runs its body, then comes back to the line after the call. Press Debug and step through it to see the jumps happen line by line.

A function can call other functions

# the two lines every program starts with: the commands, then the robot
from bugbot import *
connect()

def signal():
    led("red")
    tone(880, 0.2)
    led("off")

def side():
    forward(60, distance=20)
    signal()
    turn_right(30, angle=90)

side()
side()
side()
side()

Run this in the simulator

side uses signal, and the main program uses side. Each function is small and does one job, and the four side() calls read almost like English: drive a square, signalling at each corner.

Why write functions?

  • No repetition. The signal is written once. Change it once and every corner changes.
  • Names explain. side() says what four lines do.
  • Small pieces are easier to test. You can run signal() on its own until it is right, then build on it.
  • Teams can split the work. One person writes signal, another writes side, as long as they agree what each one does.

Task: signal at the corners

Write a function signal() that turns the LED red, plays a short note, and turns the LED off. Then drive a square of 25 cm sides, calling signal() at every corner. Call your function; do not repeat its lines.

# the two lines every program starts with: the commands, then the robot
from bugbot import *
connect()

def signal():
    led("red")

forward(60, distance=25)
turn_right(30, angle=90)

Challenges

  1. Write siren() that alternates two notes four times, and call it at the start and the end of a drive.
  2. Put the four side() calls inside a function square(), and call square() twice.
  3. What happens if you call a function inside itself? Try it with a function that only prints, and read the error.