Day 16 - Working with Lists
Outcomes:
Iterative List Processing with for each
Loops and Variables
1. Review: Variables, Mutation, and for each
Loops (10 minutes)
A. Variables and Mutation
- Mutable Variables in Pyret:
- Declare mutable variables with
var
and update them with:=
. - Example:
var total = 0
spy: total end
total := total + 5
spy: total end - Key Point: When you update a variable with
:=
, its binding in the directory changes to the new value.
- Declare mutable variables with
B. The for each
Loop
- Syntax and Purpose:
- Pyret’s
for each
loop iterates over every element of a list, performing side‑effects (such as updating a variable). - Syntax:
for each(elem from some-list):
<body that uses elem>
end
- Pyret’s
- Example – Summing Numbers:
var sum = 0
for each(n from [list: 0, 1, 2, 3]):
sum := sum + n
end
check:
sum is 6
end
C. Multi‑Statement Function Bodies with block:
- Important Syntax Rule:
- When a function body contains more than one statement, you must begin the body with
block:
. - Example:
fun my-len(l :: List<Any>) -> Number block:
var count = 0
for each(elem from l):
count := count + 1
end
count
end
- When a function body contains more than one statement, you must begin the body with
2. Structural Problems with Scalar Answers (20 minutes)
TODO: REPLACE THIS WITH A DIFFERENT EXAMPLE! WE JUST DID THIS!
A. Implementing my-sum
(Sum of Numbers)
- Problem: Compute the sum of a list of numbers.
- Iterative Strategy:
- Use a mutable variable
total
starting at 0. - For each number in the list, add it to
total
.
- Use a mutable variable
- Code:
fun my-sum(l :: List<Number>) -> Number block:
var total = 0
for each(n from l):
total := total + n
end
total
end - Exercise:
- “Predict the output of
my-sum([list: 7, 8, 9])
.” - Expected answer: 24
- “Predict the output of
3. Structural Problems that Transform or Select from Lists (20 minutes)
A. Implementing my-doubles
(Doubling Each Element)
- Problem: Produce a new list with each number doubled.
- Iterative Strategy:
- Initialize a mutable variable
result
asempty
. - For each element in the input list, append its doubled value using the list concatenation operator
+
.
- Initialize a mutable variable
- Code:
fun my-doubles(l :: List<Number>) -> List<Number> block:
var result = empty
for each(n from l):
result := result + [list: n * 2]
end
result
end - Exercise:
- “What is
my-doubles([list: 3, 5, 2])
?” - Expected answer:
[list: 6, 10, 4]
- “What is
B. Implementing my-str-len
(String Lengths)
- Problem: Given a list of strings, return a list of their lengths.
- Iterative Strategy:
- Use a mutable variable
result
initialized toempty
. - For each string, calculate
string-length(s)
and append it.
- Use a mutable variable
- Code:
fun my-str-len(l :: List<String>) -> List<Number> block:
var result = empty
for each(s from l):
result := result + [list: string-length(s)]
end
result
end - Exercise:
- “Test
my-str-len([list: "hi", "there", "mateys"])
.” - Expected answer:
[list: 2, 5, 6]
- “Test
C. Implementing my-pos-nums
(Selecting Positive Numbers)
- Problem: Return a list containing only the positive numbers.
- Iterative Strategy:
- Use a mutable variable
result
starting asempty
. - For each number, if it is greater than 0, append it using
+
.
- Use a mutable variable
- Code:
fun my-pos-nums(l :: List<Number>) -> List<Number> block:
var result = empty
for each(n from l):
when n > 0:
result := result + [list: n]
end
end
result
end - Exercise:
- “What is
my-pos-nums([list: 1, -2, 3, -4])
?” - Expected answer:
[list: 1, 3]
- “What is
D. Implementing my-alternating
(Selecting Every Other Element)
- Problem: Return a list of alternating elements (keep the first, skip the second, etc.).
- Iterative Strategy:
- Declare a mutable variable
result
(initiallyempty
) and a Booleankeep
(initiallytrue
). - For each element in the list, if
keep
is true, append it using+
, then togglekeep
(i.e.,keep := not(keep)
).
- Declare a mutable variable
- Code:
fun my-alternating(l :: List<Any>) -> List<Any> block:
var result = empty
var keep = true
for each(elem from l):
when keep:
result := result + [list: elem]
end
keep := not(keep)
end
result
end - Exercise:
- “Test
my-alternating([list: 1, 2, 3, 4, 5, 6])
. What do you get?” - Expected answer:
[list: 1, 3, 5]
- “Test
4. Wrap-Up and Discussion (5 minutes)
- Key Points Review:
- We use mutable variables (declared with
var
and updated with:=
) as accumulators. - The
for each
loop iterates over each element in a list. - When a function’s body has multiple statements, we begin with
block:
to indicate a sequence of statements. - To append two lists, we use the
+
operator (e.g.,result + [list: value]
).
- We use mutable variables (declared with
5. Optional Challenge (if time permits)
- Challenge Exercise –
my-running-sum
:- Write a function that computes the running sum of a list of numbers.
- Iterative Strategy:
- Use a mutable variable
acc
(initialized to 0) andresult
(initialized toempty
). - For each number, update
acc
withacc := acc + n
and then appendacc
toresult
using+
.
- Use a mutable variable
- Code Example:
fun my-running-sum(l :: List<Number>) -> List<Number> block:
var result = empty
var acc = 0
for each(n from l):
acc := acc + n
result := result + [list: acc]
end
result
end - Exercise:
- “What is
my-running-sum([list: 1, 2, 3, 4, 5])
?” - Expected answer:
[list: 1, 3, 6, 10, 15]
- “What is