The answersDownload the PDF
Worksheet

A13.1 The functional paradigm

Functional programming · A level · OCR H446 1.2.4, AQA 7517 4.12.2.1, Eduqas A500QS 1.4 · about 20 min

BugBotLab
NameClassDate

What this lesson is about

Side effects, pure functions and referential transparency, immutability and statelessness, with the robot's side effects kept at the edges.

Questions 6 marks in all

  1. [1 mark]Which best describes a pure function?

    1. AIts result depends only on its arguments and it has no side effects
    2. BIt is written without any if statements
    3. CIt never takes more than one argument
    4. DIt is defined inside a class
  2. [1 mark]Which of these are side effects of a function?

    Tick every answer that is true.

    1. APrinting a message
    2. BChanging a global variable
    3. CReturning a value
    4. DReading the distance sensor
    5. EWorking out the square root of its argument
  3. [1 mark]What does this program print?

    calls = 0
    
    def next_id(name):
        global calls
        calls = calls + 1
        return name + str(calls)
    
    print(next_id("bot"), next_id("bot"))
  4. [1 mark]What does this program print?

    a = [1, 2]
    b = a
    a = a + [3]
    print(b)
  5. [1 mark]A call to a pure function can always be replaced by the value it returns without changing what the program does. What is this property called?

  6. [1 mark]What does statelessness mean in functional programming?

    1. AThere is no program state that changes as the program runs: a name, once given a value, keeps it
    2. BThe program has no variables at all
    3. CThe program cannot store data in files
    4. DFunctions cannot take parameters

The task: make it pure

The starter has two impure functions. Rewrite both as pure functions, with no global and nothing changed in place: - count_clear(readings, limit): readings is a tuple of distances in cm (floats), limit a number of cm. It returns how many readings are greater than limit, and gives the same answer however many times it is called. - add_reading(log, cm): log is a tuple of floats and cm a float. It returns a new tuple with cm added at the end, and leaves log exactly as it was. The main program (keep it as it is) prints clear: 2 twice, then before: (31.0, 51.0, 15.0, 44.0) and after: (31.0, 51.0, 15.0, 44.0, 60.0). Write the functions in the stateless style: no global, no for or while loop (use recursion, as total_of does), and no append, extend or += anywhere.

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

READINGS = (31.0, 51.0, 15.0, 44.0)

count = 0
def count_clear(readings, limit):
    global count
    for cm in readings:
        if cm > limit:
            count = count + 1
    return count

def add_reading(log, cm):
    log = list(log)
    log.append(cm)
    return tuple(log)

print("clear:", count_clear(READINGS, 40))
print("clear:", count_clear(READINGS, 40))
new_log = add_reading(READINGS, 60.0)
print("before:", READINGS)
print("after:", new_log)

Plan your program here, then type it in and press Run.

QR code
Do it on the robot
www.bugbotlab.com/learn/a13-1-the-functional-paradigm/
The simulator checks it and tells you when it passes. Nothing to install, no account.

Challenges

  1. Write a pure function furthest(readings) that returns the largest reading, using recursion and no loop.
  2. Which of these are pure: len, print, random.randint, abs, input, heading? Say why for each.
  3. Write add_reading in Haskell, using ++ to join lists. Why does Haskell not need a separate "copy" step?