Class summary: Functions over Tables
Copyright (c) 2017 Kathi Fisler
1 Why and When to Make Functions
So far, we have seen three situations in which it makes sense to create a function:
To give a shorthand name to a computation that is repeated in your code (e.g., three-stripe-flag)
To set up a computation that you expect to reuse later (e.g., show-ad)
To set up a computation for which some data will be provided later (e.g., using filter-by)
The first arises when you are trying to write clean code. The second arises if you are being proactive: you have data on which to do a computation now, but you think you’ll get more of similar data later. The third is perhaps the most interesting: you know the computation you want to do, but some other (part of the) program will supply the data later. In each case, the function mechanism names a computation and details the data that it will need to complete the computation. This is an idea that we can make more concrete with tables.
2 Getting Started on Problems
The problems we’re writing code for are starting to get a bit harder, and you might not be sure how/where to start. So let’s review/practice this.
Curious about whether your course makes it possible for students to improve as the semester goes on, you want to know the percentage of students who improved from exam1 to exam2. Produce a program that will perform this computation on your gradebook.
Do you understand what data you have to work with? Write a small concrete example (whether on paper or in code).
Do you understand what output you are expecting on that concrete example? Write it down (otherwise you can lie to yourself about whether you actually know what the output is).
What are (some of) the steps or tasks that will be needed for this computation? Write them down, along with ideas of things you’ve learned in class that can help with these.
The lecture capture shows how we worked through these for this specific problem.
Key idea in CS: Diving into writing code before you’ve thought about your data and some of the steps is a great way to lengthen the time you spend working on an assignment!
3 Working with More Realistic Data
Until now, we’ve worked with our small gradebook table. Let’s start looking at a more realistic scenario: you store your gradebook in a spreadsheet and want to load it up to run some analysis on it. What might that look like in Pyret?
Pyret can load tables from Google Sheets. Here’s an example of what the code looks like:
# the string is a google sheet url identifier |
grades-raw = |
load-spreadsheet("1q7kWdnIYrNthKJ2W4vkh51wp4earjNJB2r9CVjkO-u4") |
|
# give names to the columns of the loaded table |
gradebook-real = |
load-table: name :: String, SNC :: Boolean, |
exam1 :: Number, exam2 :: Number, gradyear :: Number |
# "Sheet2" names a sheet in the table, true means there are |
# headers. The column names come from the load-table line, |
# not from the header names in the google sheet |
source: grades-raw.sheet-by-name("Sheet2", true) |
end |
Enter and run this to see the larger table available in Pyret. This particular table also has a column for the graduation year of each student.
4 Functions over Tables
Now, we want to redo our percentage-improving computation with the real table. Last time, we wrote it just on the gradebook table. Here, we turned it into a function. This way, we can use either the small gradebook table or the real gradebook table, without rewriting our code.
Write a function that takes a gradebook table and returns the number of students taking the class for a grade who got lower than 55 on exam2.
But how do we write test cases for a function like this? This is where the little gradebook table comes in. You write your tests on the little table to gain confidence in your code, then use it for computations on the larger table. See the posted code file and the lecture capture for details.